139 Commits

Author SHA1 Message Date
Tim Ruffing
acf5c55ae6 Merge bitcoin-core/secp256k1#1312: release: Prepare for 0.3.2
d490ca2046 release: Prepare for 0.3.2 (Tim Ruffing)

Pull request description:

ACKs for top commit:
  sipa:
    ACK d490ca2046
  hebasto:
    ACK d490ca2046
  jonasnick:
    ACK d490ca2046

Tree-SHA512: 0785e9654974b25977dcdb00fe2e91d79a941143d278e315b96238e18c7aedd5814c2534c0aff356d8d4bb456ff8b815bea3657b99243e0a8296bbe635329cfb
2023-05-13 19:41:35 +02:00
Tim Ruffing
d490ca2046 release: Prepare for 0.3.2 2023-05-12 22:52:30 +02:00
Tim Ruffing
3e3d125b83 Merge bitcoin-core/secp256k1#1309: changelog: Catch up
697e1ccf4a changelog: Catch up (Tim Ruffing)
76b43f3443 changelog: Add entry for #1303 (Tim Ruffing)

Pull request description:

ACKs for top commit:
  sipa:
    ACK 697e1ccf4a
  jonasnick:
    ACK 697e1ccf4a

Tree-SHA512: cfeb513effc69925bdedd3a298b1e2e5bf7709f68b453a5f157c584560b5400c3dc8b9ce87a775281cdea9db7f44e7e1337fbc93563f6efe350fe5defacbc4f6
2023-05-12 17:26:29 +02:00
Pieter Wuille
e8295d07ab Merge bitcoin-core/secp256k1#1311: Revert "Remove unused scratch space from API"
3ad1027a40 Revert "Remove unused scratch space from API" (Jonas Nick)

Pull request description:

  This reverts commit 712e7f8722.

  Removing the scratch space from the API may break bindings to the library.

ACKs for top commit:
  sipa:
    ACK 3ad1027a40
  real-or-random:
    ACK 3ad1027a40

Tree-SHA512: ad394c0a2f83fe3a5f400c0e8f2b9bf40037ce4141d4414e6345918f5e6003c61da02a538425a49bdeb5700f5ecb713bd58f5752c0715fb1fcc4950099fdc0e6
2023-05-12 11:14:57 -04:00
Tim Ruffing
697e1ccf4a changelog: Catch up 2023-05-12 17:09:00 +02:00
Jonas Nick
3ad1027a40 Revert "Remove unused scratch space from API"
This reverts commit 712e7f8722.
2023-05-12 15:05:57 +00:00
Tim Ruffing
76b43f3443 changelog: Add entry for #1303 2023-05-12 16:44:03 +02:00
Jonas Nick
7d4f86d242 Merge bitcoin-core/secp256k1#1307: Mark more assembly outputs as early clobber
8c9ae37a5a Add release note (Pieter Wuille)
350b4bd6e6 Mark stack variables as early clobber for technical correctness (Pieter Wuille)
0c729ba70d Bugfix: mark outputs as early clobber in scalar x86_64 asm (Pieter Wuille)

Pull request description:

ACKs for top commit:
  real-or-random:
    ACK 8c9ae37a5a
  jonasnick:
    ACK 8c9ae37a5a

Tree-SHA512: 874d01f5540d14b5188aec25f6441dbc6631f8d3980416040a3e250f1aef75150068415e7a458a9a3fb0d7cbdeb97f5c7e089b187d6d3dd79aa6e45274c241b6
2023-05-12 13:37:09 +00:00
Tim Ruffing
b54a0672ef Merge bitcoin-core/secp256k1#1304: build: Rename arm to arm32 and check if it's really supported
c6bb29b303 build: Rename `64bit` to `x86_64` (Hennadii Stepanov)
03246457a8 autotools: Add `SECP_ARM32_ASM_CHECK` macro (Hennadii Stepanov)
ed4ba238e2 cmake: Add `check_arm32_assembly` function (Hennadii Stepanov)
e5cf4bf3ff build: Rename `arm` to `arm32` (Hennadii Stepanov)

Pull request description:

  Closes https://github.com/bitcoin-core/secp256k1/issues/1034.

  Solves one item in https://github.com/bitcoin-core/secp256k1/issues/1235.

ACKs for top commit:
  real-or-random:
    ACK c6bb29b303 tested on x86_64 but not on ARM

Tree-SHA512: c3615a18cfa30bb2cc53be18c09ccab08fc800b84444d8c6b333347b4db039a3981da61e7da5086dd9f4472838d7c031d554be9ddc7c435ba906852bba593982
2023-05-12 14:58:32 +02:00
Hennadii Stepanov
c6bb29b303 build: Rename 64bit to x86_64 2023-05-12 10:50:18 +01:00
Pieter Wuille
8c9ae37a5a Add release note 2023-05-12 05:47:59 -04:00
Hennadii Stepanov
03246457a8 autotools: Add SECP_ARM32_ASM_CHECK macro 2023-05-12 10:38:51 +01:00
Hennadii Stepanov
ed4ba238e2 cmake: Add check_arm32_assembly function 2023-05-12 10:38:50 +01:00
Pieter Wuille
350b4bd6e6 Mark stack variables as early clobber for technical correctness
In the field 5x52 asm for x86_64, stack variables are provided as outputs.
The existing inputs are all forcibly allocated to registers, so cannot
coincide, but mark them as early clobber anyway to make this clearer.
2023-05-12 05:23:11 -04:00
Pieter Wuille
0c729ba70d Bugfix: mark outputs as early clobber in scalar x86_64 asm
In the existing code, the compiler is allowed to allocate the RSI register
for outputs m0, m1, or m2, which are written to before the input in RSI is
read from. Fix this by marking them as early clobber.

Reported by ehoffman2 in https://github.com/bitcoin-core/secp256k1/issues/766
2023-05-12 05:23:07 -04:00
Pieter Wuille
3353d3c753 Merge bitcoin-core/secp256k1#1207: Split fe_set_b32 into reducing and normalizing variants
5b32602295 Split fe_set_b32 into reducing and normalizing variants (Pieter Wuille)

Pull request description:

  Follow-up to #1205.

  This splits the `secp256k1_fe_set_b32` function into two variants:
  * `secp256k1_fe_set_b32_mod`, which returns `void`, reduces modulo the curve order, and only promises weakly normalized output.
  * `secp256k1_fe_set_b32_limit`, which returns `int` indicating success/failure, and only promises valid output in case the input is in range (but guarantees it's strongly normalized in this case).

  This removes one of the few cases in the codebase where normalization status depends on runtime values, making it fixed at compile-time instead.

ACKs for top commit:
  real-or-random:
    ACK 5b32602295
  jonasnick:
    ACK 5b32602295

Tree-SHA512: 4b93502272638c6ecdef4d74afa629e7ee540c0a20b377dccedbe567857b56c4684fad3af4b4293ed7ba35fed4aa5d0beaacdd77a903f44f24e8d87305919b61
2023-05-11 16:06:15 -04:00
Pieter Wuille
5b32602295 Split fe_set_b32 into reducing and normalizing variants 2023-05-11 13:49:33 -04:00
Jonas Nick
006ddc1f42 Merge bitcoin-core/secp256k1#1306: build: Make tests work with external default callbacks
1907f0f166 build: Make tests work with external default callbacks (Tim Ruffing)

Pull request description:

ACKs for top commit:
  sipa:
    ACK 1907f0f166
  jonasnick:
    ACK 1907f0f166

Tree-SHA512: 198598f7bf5292bf5709187f9a40ddf9a0fba93e8b62afb49df2c05b4ef61c394cea43ee07615b51ceea97862228d8ad351fddef13c190cb2e6690943ed63128
2023-05-11 17:31:29 +00:00
Tim Ruffing
1907f0f166 build: Make tests work with external default callbacks 2023-05-11 19:08:35 +02:00
Jonas Nick
fb3a806365 Merge bitcoin-core/secp256k1#1133: schnorrsig: Add test vectors for variable-length messages
cd54ac7c1c schnorrsig: Improve docs of schnorrsig_sign_custom (Tim Ruffing)
28687b0312 schnorrsig: Add BIP340 varlen test vectors (Tim Ruffing)
97a98bed1e schnorrsig: Refactor test vector code to allow varlen messages (Tim Ruffing)

Pull request description:

ACKs for top commit:
  sipa:
    ACK cd54ac7c1c. I didn't verify the included test vectors match the BIP.
  jonasnick:
    ACK cd54ac7c1c

Tree-SHA512: 268140e239b703aaf79825de2263675a8c31bef999f013ea532b0cd7b80f2d600d78f3872209a93774ba4dbc0a046108e87d151fc4604882c5636876026a0816
2023-05-11 16:44:08 +00:00
Tim Ruffing
cd54ac7c1c schnorrsig: Improve docs of schnorrsig_sign_custom 2023-05-11 18:36:42 +02:00
Tim Ruffing
28687b0312 schnorrsig: Add BIP340 varlen test vectors 2023-05-11 18:36:42 +02:00
Tim Ruffing
97a98bed1e schnorrsig: Refactor test vector code to allow varlen messages 2023-05-11 18:36:42 +02:00
Jonas Nick
ab5a917128 Merge bitcoin-core/secp256k1#1303: ct: Use more volatile
17fa21733a ct: Be cautious and use volatile trick in more "conditional" paths (Tim Ruffing)
5fb336f9ce ct: Use volatile trick in scalar_cond_negate (Tim Ruffing)

Pull request description:

ACKs for top commit:
  sipa:
    ACK 17fa21733a
  jonasnick:
    ACK 17fa21733a

Tree-SHA512: 4a0fbee7b1cce4f4647bff697c0e645d93aa8fb49777feef5eb1e1eadce2116bafdcc6175c066ee4fe4bf1340047311e2d7d2c48bb288867a837ecd6c8687121
2023-05-11 16:14:44 +00:00
Tim Ruffing
9eb6934f69 Merge bitcoin-core/secp256k1#1305: Remove unused scratch space from API
712e7f8722 Remove unused scratch space from API (Jonas Nick)

Pull request description:

  Not sure if we want the typedef and `secp256k1_scratch_space_{create,destroy}` but if we don't keep them then this PR will be a rather large diff.

ACKs for top commit:
  sipa:
    ACK 712e7f8722
  real-or-random:
    utACK 712e7f8722

Tree-SHA512: b3a8feb0fe4639d5e48b708ccbf355bca5da658a291f63899086d2bbeb6d0ab33e3dcd55d8984ec7fa803f757b7d02e71bcb7e7eeecaab52ffc70ae85dce8c44
2023-05-11 18:07:53 +02:00
Jonas Nick
073d98a076 Merge bitcoin-core/secp256k1#1292: refactor: Make 64-bit shift explicit
d1e48e5474 refactor: Make 64-bit shift explicit (Hennadii Stepanov)
b2e29e43d0 ci: Treat all compiler warnings as errors in "Windows (VS 2022)" task (Hennadii Stepanov)

Pull request description:

ACKs for top commit:
  real-or-random:
    utACK d1e48e5474
  jonasnick:
    ACK d1e48e5474

Tree-SHA512: fd07c8c136b1c947900d45b5a4ad4963e2c29884aca62a26be07713dfd1b0c5e7655f07a0b99217fc055bf3266e71cb5edabbd4d5c145a172b4be5d10f7ad51c
2023-05-11 15:06:47 +00:00
Tim Ruffing
17fa21733a ct: Be cautious and use volatile trick in more "conditional" paths
- secp256k1_scalar_cadd_bit
 - secp256k1_modinvXX_normalize_YY
 - secp256k1_modinvXX_divsteps_ZZ
 - ECMULT_CONST_TABLE_GET_GE

Even though those code loations are not problematic right now
(with current compilers).
2023-05-11 16:32:07 +02:00
Tim Ruffing
5fb336f9ce ct: Use volatile trick in scalar_cond_negate 2023-05-11 16:32:07 +02:00
Jonas Nick
712e7f8722 Remove unused scratch space from API 2023-05-11 13:39:56 +00:00
Pieter Wuille
54d34b6c24 Merge bitcoin-core/secp256k1#1300: Avoid normalize conditional on VERIFY
97c63b9039 Avoid normalize conditional on VERIFY (Pieter Wuille)

Pull request description:

  In the old code, `secp256k1_gej_rescale` requires a normalized input in VERIFY mode, but not otherwise. Its requirements shouldn't depend on this mode being enabled or not.

ACKs for top commit:
  real-or-random:
    utACK 97c63b9039 I've also verified that the loop in secp256k1_ecmult_strauss_wnaf holds up the invariant that the magnitude of Z is 1, even with the normalization removed
  jonasnick:
    ACK 97c63b9039

Tree-SHA512: 9598c133c6f4e488c74512089dabe0508529f20ca782be1c8fbeae9d7f132da9d570a061053acd3d245a9a187abf1f2581207441ce6aac8d0f8972cf357a349f
2023-05-11 08:30:21 -04:00
Pieter Wuille
c63ec88ebf Merge bitcoin-core/secp256k1#1066: Abstract out and merge all the magnitude/normalized logic
7fc642fa25 Simplify secp256k1_fe_{impl_,}verify (Pieter Wuille)
4e176ad5b9 Abstract out verify logic for fe_is_square_var (Pieter Wuille)
4371f98346 Abstract out verify logic for fe_add_int (Pieter Wuille)
89e324c6b9 Abstract out verify logic for fe_half (Pieter Wuille)
283cd80ab4 Abstract out verify logic for fe_get_bounds (Pieter Wuille)
d5aa2f0358 Abstract out verify logic for fe_inv{,_var} (Pieter Wuille)
3167646072 Abstract out verify logic for fe_from_storage (Pieter Wuille)
76d31e5047 Abstract out verify logic for fe_to_storage (Pieter Wuille)
1e6894bdd7 Abstract out verify logic for fe_cmov (Pieter Wuille)
be82bd8e03 Improve comments/checks for fe_sqrt (Pieter Wuille)
6ab35082ef Abstract out verify logic for fe_sqr (Pieter Wuille)
4c25f6efbd Abstract out verify logic for fe_mul (Pieter Wuille)
e179e651cb Abstract out verify logic for fe_add (Pieter Wuille)
7e7ad7ff57 Abstract out verify logic for fe_mul_int (Pieter Wuille)
65d82a3445 Abstract out verify logic for fe_negate (Pieter Wuille)
144670893e Abstract out verify logic for fe_get_b32 (Pieter Wuille)
f7a7666aeb Abstract out verify logic for fe_set_b32 (Pieter Wuille)
ce4d2093e8 Abstract out verify logic for fe_cmp_var (Pieter Wuille)
7d7d43c6dd Improve comments/check for fe_equal{,_var} (Pieter Wuille)
c5e788d672 Abstract out verify logic for fe_is_odd (Pieter Wuille)
d3f3fe8616 Abstract out verify logic for fe_is_zero (Pieter Wuille)
c701d9a471 Abstract out verify logic for fe_clear (Pieter Wuille)
19a2bfeeea Abstract out verify logic for fe_set_int (Pieter Wuille)
864f9db491 Abstract out verify logic for fe_normalizes_to_zero{,_var} (Pieter Wuille)
6c31371120 Abstract out verify logic for fe_normalize_var (Pieter Wuille)
e28b51f522 Abstract out verify logic for fe_normalize_weak (Pieter Wuille)
b6b6f9cb97 Abstract out verify logic for fe_normalize (Pieter Wuille)
7fa5195559 Bugfix: correct SECP256K1_FE_CONST mag/norm fields (Pieter Wuille)
b29566c51b Merge magnitude/normalized fields, move/improve comments (Pieter Wuille)

Pull request description:

  Right now, all the logic for propagating/computing the magnitude/normalized fields in `secp256k1_fe` (when `VERIFY` is defined) and the code for checking it, is duplicated across the two field implementations. I believe that is undesirable, as these properties should purely be a function of the performed fe_ functions, and not of the choice of field implementation. This becomes even uglier with #967, which would copy all that, and even needs an additional dimension that would then need to be added to the two other fields. It's also related to #1001, which I think will become easier if it doesn't need to be done/reasoned about separately for every field.

  This PR moves all logic around these fields (collectively called field verification) to implementations in field_impl.h, which dispatch to renamed functions in field_*_impl.h for the actual implementation.

  Fixes #1060.

ACKs for top commit:
  jonasnick:
    ACK 7fc642fa25
  real-or-random:
    ACK 7fc642fa25

Tree-SHA512: 0f94e13fedc47e47859261a182c4077308f8910495691f7e4d7877d9298385172c70e98b4a1e270b6bde4d0062b932607106306bdb35a519cdeab9695a5c71e4
2023-05-11 08:23:48 -04:00
Pieter Wuille
7fc642fa25 Simplify secp256k1_fe_{impl_,}verify 2023-05-11 06:25:59 -04:00
Pieter Wuille
4e176ad5b9 Abstract out verify logic for fe_is_square_var 2023-05-11 06:25:56 -04:00
Pieter Wuille
4371f98346 Abstract out verify logic for fe_add_int 2023-05-11 06:25:19 -04:00
Pieter Wuille
89e324c6b9 Abstract out verify logic for fe_half 2023-05-11 06:25:15 -04:00
Pieter Wuille
283cd80ab4 Abstract out verify logic for fe_get_bounds 2023-05-11 06:24:26 -04:00
Pieter Wuille
d5aa2f0358 Abstract out verify logic for fe_inv{,_var} 2023-05-11 06:24:26 -04:00
Pieter Wuille
3167646072 Abstract out verify logic for fe_from_storage 2023-05-11 06:24:26 -04:00
Pieter Wuille
76d31e5047 Abstract out verify logic for fe_to_storage 2023-05-11 06:24:26 -04:00
Pieter Wuille
1e6894bdd7 Abstract out verify logic for fe_cmov 2023-05-11 06:24:26 -04:00
Pieter Wuille
be82bd8e03 Improve comments/checks for fe_sqrt 2023-05-11 06:24:22 -04:00
Pieter Wuille
6ab35082ef Abstract out verify logic for fe_sqr 2023-05-11 06:18:40 -04:00
Pieter Wuille
4c25f6efbd Abstract out verify logic for fe_mul 2023-05-11 06:18:40 -04:00
Pieter Wuille
e179e651cb Abstract out verify logic for fe_add 2023-05-11 06:18:40 -04:00
Pieter Wuille
7e7ad7ff57 Abstract out verify logic for fe_mul_int 2023-05-11 06:18:40 -04:00
Pieter Wuille
65d82a3445 Abstract out verify logic for fe_negate 2023-05-11 06:18:40 -04:00
Pieter Wuille
144670893e Abstract out verify logic for fe_get_b32 2023-05-11 06:18:40 -04:00
Pieter Wuille
f7a7666aeb Abstract out verify logic for fe_set_b32 2023-05-11 06:18:40 -04:00
Pieter Wuille
ce4d2093e8 Abstract out verify logic for fe_cmp_var 2023-05-11 06:18:40 -04:00
Pieter Wuille
7d7d43c6dd Improve comments/check for fe_equal{,_var} 2023-05-11 06:18:40 -04:00
Pieter Wuille
c5e788d672 Abstract out verify logic for fe_is_odd 2023-05-11 06:18:40 -04:00
Pieter Wuille
d3f3fe8616 Abstract out verify logic for fe_is_zero 2023-05-11 06:18:40 -04:00
Pieter Wuille
c701d9a471 Abstract out verify logic for fe_clear 2023-05-11 06:18:40 -04:00
Pieter Wuille
19a2bfeeea Abstract out verify logic for fe_set_int 2023-05-11 06:18:40 -04:00
Pieter Wuille
864f9db491 Abstract out verify logic for fe_normalizes_to_zero{,_var} 2023-05-11 06:18:40 -04:00
Pieter Wuille
6c31371120 Abstract out verify logic for fe_normalize_var 2023-05-11 06:18:40 -04:00
Pieter Wuille
e28b51f522 Abstract out verify logic for fe_normalize_weak 2023-05-11 06:18:40 -04:00
Pieter Wuille
b6b6f9cb97 Abstract out verify logic for fe_normalize 2023-05-11 06:18:40 -04:00
Pieter Wuille
7fa5195559 Bugfix: correct SECP256K1_FE_CONST mag/norm fields 2023-05-11 06:18:37 -04:00
Hennadii Stepanov
e5cf4bf3ff build: Rename arm to arm32 2023-05-11 10:03:23 +01:00
Pieter Wuille
b29566c51b Merge magnitude/normalized fields, move/improve comments
Also split secp256k1_fe_verify into a generic and an implementation
specific part.
2023-05-11 04:25:19 -04:00
Pieter Wuille
97c63b9039 Avoid normalize conditional on VERIFY 2023-05-11 03:41:48 -04:00
Tim Ruffing
341cc19726 Merge bitcoin-core/secp256k1#1299: Infinity handling: ecmult_const(infinity) works, and group verification
bbc834467c Avoid secp256k1_ge_set_gej_zinv with uninitialized z (Pieter Wuille)
0a2e0b2ae4 Make secp256k1_{fe,ge,gej}_verify work as no-op if non-VERIFY (Pieter Wuille)
f20266722a Add invariant checking to group elements (Pieter Wuille)
a18821d5b1 Always initialize output coordinates in secp256k1_ge_set_gej (Pieter Wuille)
3086cb90ac Expose secp256k1_fe_verify to other modules (Pieter Wuille)
a0e696fd4d Make secp256k1_ecmult_const handle infinity (Gregory Maxwell)

Pull request description:

  Rebase of #791.

  * Clean up infinity handling, make x/y/z always initialized for infinity.
  * Make secp256k1_ecmult_const handle infinity.
    * Infinity isn't currently needed here, but correctly handling it is a little more safe against future changes.
    * Update docs for it to make it clear that it is not constant time in Q. It never was constant time in Q (and would be a little complicated to make constant time in Q: needs a constant time addition function that tracks RZR). It isn't typical for ECDH to be constant time in terms of the pubkey. If it was later made constant time in Q infinity support would be easy to preserve, e.g. by running it on a dummy value and cmoving infinity into the output.
  * Add group verification (`secp256k1_ge_verify` and `secp256k1_gej_verify`, mimicking `secp256k1_fe_verify`).
  * Make the `secp256k1_{fe,ge,gej}_verify` functions also defined (as no-ops) in non-VERIFY mode.

ACKs for top commit:
  jonasnick:
    ACK bbc834467c
  real-or-random:
    ACK bbc834467c

Tree-SHA512: 82cb51faa2c207603aa10359a311ea618fcb5a81ba175bf15515bf84043223db6428434875854cdfce9ae95f9cfd68c74e4e415f26bd574f1791b5dec1615d19
2023-05-10 18:44:18 +02:00
Pieter Wuille
bbc834467c Avoid secp256k1_ge_set_gej_zinv with uninitialized z 2023-05-10 09:25:09 -04:00
Pieter Wuille
0a2e0b2ae4 Make secp256k1_{fe,ge,gej}_verify work as no-op if non-VERIFY 2023-05-10 09:25:09 -04:00
Pieter Wuille
f20266722a Add invariant checking to group elements 2023-05-10 09:25:09 -04:00
Pieter Wuille
a18821d5b1 Always initialize output coordinates in secp256k1_ge_set_gej 2023-05-10 09:25:06 -04:00
Pieter Wuille
3086cb90ac Expose secp256k1_fe_verify to other modules 2023-05-10 09:06:02 -04:00
Gregory Maxwell
a0e696fd4d Make secp256k1_ecmult_const handle infinity
Infinity isn't currently needed here, but correctly handling it is a
little more safe against future changes.

Update docs for it to make it clear that it is not constant time in A
(the input point). It never was constant time in Q (and would be a little
complicated to make constant time in A).

If it was later made constant time in A, infinity support would be easy
to preserve, e.g. by running it on a dummy value and cmoving infinity into
the output.
2023-05-10 09:06:02 -04:00
Tim Ruffing
24c768ae09 Merge bitcoin-core/secp256k1#1301: Avoid using bench_verify_data as bench_sign_data; merge them
2e65f1fdbc Avoid using bench_verify_data as bench_sign_data; merge them (Pieter Wuille)

Pull request description:

  The existing bench.c code defines `bench_verify_data data` variable, but some of the benchmarks then use it as `bench_sign`. Fix this by merging the two types into one.

ACKs for top commit:
  stratospher:
    ACK 2e65f1f.
  real-or-random:
    utACK 2e65f1fdbc

Tree-SHA512: 676b43e5d30abd13bfd9595378b1a0bd90a2e713be4f8f713260f989ea8c971b229dfb683cd7a1614665b1688a0bdda7a4019f358dd6cd645e1b3d9f8d71e814
2023-05-10 10:03:25 +02:00
Pieter Wuille
2e65f1fdbc Avoid using bench_verify_data as bench_sign_data; merge them 2023-05-09 14:00:43 -04:00
Jonas Nick
1cf15ebd94 Merge bitcoin-core/secp256k1#1296: docs: complete interface description for secp256k1_schnorrsig_sign_custom
149c41cee1 docs: complete interface description for `secp256k1_schnorrsig_sign_custom` (Sebastian Falbesoner)

Pull request description:

ACKs for top commit:
  real-or-random:
    utACK 149c41cee1
  jonasnick:
    ACK 149c41cee1

Tree-SHA512: ee677ed6b474b547066ce149688edab7ba6d2572acfbc0989256a669341fff4cf2e17b451cd3fc6fff3944a896647f0f5c1411056678505fa85ba71e8cfe6229
2023-05-09 10:44:27 +00:00
Sebastian Falbesoner
149c41cee1 docs: complete interface description for secp256k1_schnorrsig_sign_custom
For the sake of completeness, add the missing descriptions for the
return value and parameters (`ctx`, `sig64`, `keypair`), in the same
wording/style as for the function `secp256k1_schnorrsig_sign32`.
2023-05-08 13:09:42 +02:00
Tim Ruffing
f30c74866b Merge bitcoin-core/secp256k1#1270: cmake: Fix library ABI versioning
bef448f9af cmake: Fix library ABI versioning (Hennadii Stepanov)

Pull request description:

  This change emulates Libtool to make sure Libtool and CMake agree on the ABI version.

  To test, one needs to simulate a release with backward-compatible API changes, which means the following changes in `configure.ac` and `CMakeLists.txt`:
  - incrementing of `*_LIB_VERSION_CURRENT`
  - setting `*_LIB_VERSION_REVISION` to zero
  - incrementing of `*_LIB_VERSION_AGE`

ACKs for top commit:
  real-or-random:
    ACK bef448f9af  diff looks good and I tested on Linux

Tree-SHA512: f7551fc7377ea50c8bc32d14108a034a1f91ebbb63d5fec562e5cc28416637834b9a4dcba3692df1780adcd1212ad4f238dc0219ab5add68bd88a5a458572ee5
2023-05-03 15:58:55 +02:00
Hennadii Stepanov
d1e48e5474 refactor: Make 64-bit shift explicit
This change fixes MSVC level-3 warning C4334.
See: https://learn.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-3-c4334

Required to enable level 3 warnings (/W3).
2023-05-02 13:35:15 +01:00
Hennadii Stepanov
b2e29e43d0 ci: Treat all compiler warnings as errors in "Windows (VS 2022)" task 2023-04-30 16:46:03 +01:00
Tim Ruffing
3c81838856 Merge bitcoin-core/secp256k1#1289: cmake: Use full signature of add_test() command
755629bc03 cmake: Use full signature of `add_test()` command (Hennadii Stepanov)

Pull request description:

  This PR fixes tests for Windows binaries using Wine:
  ```
  $ cmake -S . -B ../mingw -DCMAKE_TOOLCHAIN_FILE=cmake/x86_64-w64-mingw32.toolchain.cmake
  $ cmake --build ../mingw
  $ cmake --build ../mingw -t check
  Test project /home/hebasto/git/secp256k1/mingw
      Start 1: noverify_tests
  Could not find executable noverify_tests
  ...
  ```

ACKs for top commit:
  real-or-random:
    ACK 755629bc03

Tree-SHA512: d1b24a1f1de2e8b70203132f4f6e685b9a120a987302cefe033fa916dfe7a135dbacaf8174d4046e30be170e92a16d070db54292c038cd2acdecc334f7f516dd
2023-04-29 17:17:47 +02:00
Hennadii Stepanov
755629bc03 cmake: Use full signature of add_test() command
An executable target in the `COMMAND` option will automatically be
replaced by the location of the executable created at build time.

This change fixes tests for Windows binaries using Wine.
2023-04-29 09:49:25 +01:00
Hennadii Stepanov
bef448f9af cmake: Fix library ABI versioning
This change emulates Libtool to make sure Libtool and CMake agree on the
ABI version.
2023-04-28 20:59:53 +01:00
Tim Ruffing
4b0f711d46 Merge bitcoin-core/secp256k1#1277: autotools: Clean up after adding Wycheproof
7e977b3c50 autotools: Take VPATH builds into account when generating testvectors (Tim Ruffing)
2418d3260a autotools: Create src/wycheproof dir before creating file in it (Tim Ruffing)
8764034ed5 autotools: Make all "pregenerated" targets .PHONY (Tim Ruffing)
e1b9ce8811 autotools: Use same conventions for all pregenerated files (Tim Ruffing)
08f4b1632d autotools: Move code around to tidy Makefile (Tim Ruffing)
529b54d922 autotools: Move Wycheproof header from EXTRA_DIST to noinst_HEADERS (Tim Ruffing)

Pull request description:

  Follow-up to https://github.com/bitcoin-core/secp256k1/pull/1245.

  This builds on top of https://github.com/bitcoin-core/secp256k1/pull/1276. Let's only merge https://github.com/bitcoin-core/secp256k1/pull/1276 as a hotfix for the Core build.

ACKs for top commit:
  hebasto:
    ACK 7e977b3c50

Tree-SHA512: 42e09feaed15d903e759360e1dfbd1afce9da07a55512e2e791147b72d9b6477e34ae6028439af57dbcae318081a37ddcf3a630f9617bfea95c130135ba2313f
2023-04-27 15:39:30 +01:00
Tim Ruffing
222ecaf661 Merge bitcoin-core/secp256k1#1284: cmake: Some improvements using PROJECT_IS_TOP_LEVEL variable
71f746c057 cmake: Include `include` directory for subtree builds (Hennadii Stepanov)
5431b9decd cmake: Make `SECP256K1_INSTALL` default depend on `PROJECT_IS_TOP_LEVEL` (Hennadii Stepanov)
162608cc98 cmake: Emulate `PROJECT_IS_TOP_LEVEL` for CMake<3.21 (Hennadii Stepanov)

Pull request description:

  This PR:
  1. Emulates [`PROJECT_IS_TOP_LEVEL`](https://cmake.org/cmake/help/latest/variable/PROJECT_IS_TOP_LEVEL.html) variable for CMake versions where it is not available.
  2. Makes the `SECP256K1_INSTALL` option dependent on `PROJECT_IS_TOP_LEVEL` (a [follow up](https://github.com/bitcoin-core/secp256k1/pull/1263#issuecomment-1516564300) of https://github.com/bitcoin-core/secp256k1/pull/1263).
  3. Makes integration of this project as a subtree easier. A top project can `#include <secp256k1.h>` with no additional `target_include_directories()` commands. For example, see https://github.com/hebasto/secp256k1-CMake-example/tree/subtree.

ACKs for top commit:
  theuni:
    utACK 71f746c057.

Tree-SHA512: 8ccdbcc94b26f36e772611ebaab0f2846debd6ad20f9e361be31a8d2128a14273acb692b0631026e12cc6cdef6d445dce0fd3beb4f71af47b46dfcf840a18879
2023-04-27 15:17:38 +01:00
Hennadii Stepanov
71f746c057 cmake: Include include directory for subtree builds 2023-04-27 15:13:10 +01:00
Tim Ruffing
024a409484 Merge bitcoin-core/secp256k1#1240: cmake: Improve and document compiler flag checks
a8d059f76c cmake, doc: Document compiler flags (Hennadii Stepanov)
6ece1507cb cmake, refactor: Rename `try_add_compile_option` to `try_append_cflags` (Hennadii Stepanov)
19516ed3e9 cmake: Use `add_compile_options()` in `try_add_compile_option()` (Hennadii Stepanov)

Pull request description:

  This PR:
  - drops tinkering with the `COMPILE_OPTIONS` directory property in `try_add_compile_option()`  and renames it to `try_append_cflags()`
  - copies related comments from `configure.ac`

ACKs for top commit:
  theuni:
    ACK a8d059f76c .

Tree-SHA512: 7ac011c135e12a65c45f4feb7cd74fd2d961ed77252afecf3a66e2af1d57facab446120c63696507b5ecd5bdb3eee1521760a53028b914c429652d00d03a4462
2023-04-27 14:48:46 +01:00
Hennadii Stepanov
a8d059f76c cmake, doc: Document compiler flags 2023-04-27 14:41:13 +01:00
Hennadii Stepanov
6ece1507cb cmake, refactor: Rename try_add_compile_option to try_append_cflags
Actually, `try_append_cflags()` can handle a list of flags, and the new
name is similar to the one used in `configure.ac`.
2023-04-27 14:41:13 +01:00
Hennadii Stepanov
19516ed3e9 cmake: Use add_compile_options() in try_add_compile_option()
This change drops tinkering with the `COMPILE_OPTIONS` directory
property. Also `try_add_compile_option()` can handle a list of flags
now, if they are required to be checked simultaneously.

An explanatory comments have been added as well.
2023-04-27 14:39:10 +01:00
Tim Ruffing
4b84f4bf0f Merge bitcoin-core/secp256k1#1239: cmake: Bugfix and other improvements after bumping CMake up to 3.13
a273d74b2e cmake: Improve version comparison (Hennadii Stepanov)
6a58b483ef cmake: Use `if(... IN_LIST ...)` command (Hennadii Stepanov)
2445808c02 cmake: Use dedicated `GENERATOR_IS_MULTI_CONFIG` property (Hennadii Stepanov)
9f8703ef17 cmake: Use dedicated `CMAKE_HOST_APPLE` variable (Hennadii Stepanov)
8c2017035a cmake: Use recommended `add_compile_definitions` command (Hennadii Stepanov)
04d4cc071a cmake: Add `DESCRIPTION` and `HOMEPAGE_URL` options to `project` command (Hennadii Stepanov)
8a8b6536ef cmake: Use `SameMinorVersion` compatibility mode (Hennadii Stepanov)

Pull request description:

  This PR:
  - resolves two items from #1235, including a bugfix with package version compatibility
  - includes other improvements which have become available for CMake 3.13+.

  To test the `GENERATOR_IS_MULTI_CONFIG` property on Linux, one can use the "[Ninja Multi-Config](https://cmake.org/cmake/help/latest/generator/Ninja%20Multi-Config.html)" generator:
  ```sh
  cmake -S . -B build -G "Ninja Multi-Config"
  ```

ACKs for top commit:
  real-or-random:
    ACK a273d74b2e
  theuni:
    ACK a273d74b2e

Tree-SHA512: f31c4f0f30bf368303e70ab8952cde5cc8c70a5e79a04f879abcbee3d0a8d8c598379fb38f5142cb1f8ff5f9dcfc8b8eb4c13c975a1d05fdcc92d9c805a59d9a
2023-04-27 11:23:55 +01:00
Tim Ruffing
596b336ff6 Merge bitcoin-core/secp256k1#1234: cmake: Add dev-mode
ce5ba9e24d gitignore: Add CMakeUserPresets.json (Tim Ruffing)
0a446a312f cmake: Add dev-mode CMake preset (Tim Ruffing)

Pull request description:

  To use, invoke `cmake` with argument `--preset dev-mode`.

  One disadvantage over `./configure --enable-dev-mode` is that CMake does not provide a way to "hide" presets from users. That is, `cmake --list-presets` will list dev-mode, and it will also appear in `cmake-gui`, even though it's not selectable there due to a bug in cmake-gui.

  Solves one item in #1224.

ACKs for top commit:
  hebasto:
    ACK ce5ba9e24d
  theuni:
    ACK ce5ba9e24d

Tree-SHA512: c14bd283bd5bf64006bf3a23d72e6e55777b084aff71eb2a002f8ddde1d3549ccb2f08feb2b83366a24272209ab579cac8b73cfc020919adf7f039beb65bc9cc
2023-04-27 11:05:25 +01:00
Tim Ruffing
6b7e5b717d Merge bitcoin-core/secp256k1#1275: build: Fix C4005 "macro redefinition" MSVC warnings in examples
dc0657c762 build: Fix C4005 "macro redefinition" MSVC warnings in examples (Hennadii Stepanov)

Pull request description:

  This PR:
  - fixes C4005 "macro redefinition" MSVC warnings in examples
  - removes warning suppressions in both build systems, Autotools-based and CMake-based ones

ACKs for top commit:
  real-or-random:
    utACK dc0657c762

Tree-SHA512: fe3bb8f06b3ff1d51e5e20754a289e0e6b99ddf4c0bd4e6e4786e2558e71e043ab23ff7782a83a902df5db28d18ae65312674c373fdc49f5af252763a22bd0fb
2023-04-26 16:44:51 +01:00
Tim Ruffing
1c89536718 Merge bitcoin-core/secp256k1#1286: tests: remove extra semicolon in macro
c4062d6b5d debug: move helper for printing buffers into util.h (Jonas Nick)
3858bad2c6 tests: remove extra semicolon in macro (Jonas Nick)

Pull request description:

ACKs for top commit:
  real-or-random:
    utACK c4062d6b5d
  hebasto:
    ACK c4062d6b5d, I have reviewed the code and it looks OK.

Tree-SHA512: a2c97433d82c1ab2ba976c4fd8aaf337de5f225abcd459e84dcdab689e77e43d4ed654c971ab7f11f27af12e7a744122a0fdd9ece8e635d7a7041c45e9484de8
2023-04-25 23:10:00 +01:00
Jonas Nick
c4062d6b5d debug: move helper for printing buffers into util.h 2023-04-25 16:07:10 +00:00
Tim Ruffing
7e977b3c50 autotools: Take VPATH builds into account when generating testvectors 2023-04-25 16:06:25 +01:00
Tim Ruffing
2418d3260a autotools: Create src/wycheproof dir before creating file in it
This directory may not exist in a VPATH build,
see https://github.com/bitcoin/bitcoin/pull/27445#issuecomment-1502994264 .
2023-04-25 16:06:25 +01:00
Tim Ruffing
8764034ed5 autotools: Make all "pregenerated" targets .PHONY
This follows the automake conventions more, see:
https://www.gnu.org/software/automake/manual/html_node/Clean.html
2023-04-25 16:06:25 +01:00
Tim Ruffing
e1b9ce8811 autotools: Use same conventions for all pregenerated files 2023-04-25 16:06:25 +01:00
Jonas Nick
3858bad2c6 tests: remove extra semicolon in macro 2023-04-21 20:21:28 +00:00
Jonas Nick
1f33bb2b1c Merge bitcoin-core/secp256k1#1205: field: Improve docs +tests of secp256k1_fe_set_b32
162da73e9a tests: Add debug helper for printing buffers (Tim Ruffing)
e9fd3dff76 field: Improve docs and tests of secp256k1_fe_set_b32 (Tim Ruffing)
ca92a35d01 field: Simplify code in secp256k1_fe_set_b32 (Tim Ruffing)
d93f62e369 field: Verify field element even after secp256k1_fe_set_b32 fails (Tim Ruffing)

Pull request description:

ACKs for top commit:
  jonasnick:
    ACK 162da73e9a

Tree-SHA512: b3ed8e45c969d0420275ff154462f3820b72b57832ccba1f6f427e0cfd9cff3e27440c20994f69ea33a576b1903eb7f04a989f0dbd574bbd96ee56c6dd4500f7
2023-04-21 16:23:59 +00:00
Tim Ruffing
162da73e9a tests: Add debug helper for printing buffers 2023-04-21 17:20:37 +02:00
Tim Ruffing
e9fd3dff76 field: Improve docs and tests of secp256k1_fe_set_b32 2023-04-21 17:20:37 +02:00
Tim Ruffing
f6bef03c0a Merge bitcoin-core/secp256k1#1283: Get rid of secp256k1_fe_const_b
69e1ec0331 Get rid of secp256k1_fe_const_b (Pieter Wuille)

Pull request description:

  Replaces #1282.

  Its only remaining use is in a test introduced in #1118, and it is easily replaced by the new `secp256k1_fe_add_int` from #1217.

ACKs for top commit:
  real-or-random:
    utACK 69e1ec0331

Tree-SHA512: 6ada192e0643fc5326198b60f019a5081444f9ba0a5b8ba6236f2a526829d8e5e479556600a604d9bc96c7ba86e3aab813f93c66679287d2135e95a2b75f5d3e
2023-04-21 13:07:59 +02:00
Hennadii Stepanov
5431b9decd cmake: Make SECP256K1_INSTALL default depend on PROJECT_IS_TOP_LEVEL
Also full stops have been added to the option help texts for consistency
in cmake-gui.
2023-04-21 12:03:04 +01:00
Tim Ruffing
5ec1333d4f Merge bitcoin-core/secp256k1#1285: bench: Make sys/time.h a system include
68b16a1662 bench: Make sys/time.h a system include (Tim Ruffing)

Pull request description:

  just because it is minimally more correct

ACKs for top commit:
  hebasto:
    ACK 68b16a1662, I've skimmed through the whole codebase and did not find any more similar cases.

Tree-SHA512: 0a929b36202100abf0d14e9328a2dc2b4c9db5532f95514315cb04dd0a970dbbb1dc02c6275be0ec109dc88f6090f6ce48a65003c852fd4dc750decf07e563c4
2023-04-21 12:52:01 +02:00
Tim Ruffing
68b16a1662 bench: Make sys/time.h a system include 2023-04-21 11:18:36 +02:00
Hennadii Stepanov
162608cc98 cmake: Emulate PROJECT_IS_TOP_LEVEL for CMake<3.21 2023-04-20 23:12:28 +01:00
Pieter Wuille
69e1ec0331 Get rid of secp256k1_fe_const_b 2023-04-20 16:07:56 -04:00
Tim Ruffing
ce5ba9e24d gitignore: Add CMakeUserPresets.json
This file is specifically intended for *local* CMake templates
(as opposed to CMakePresets.json).
2023-04-20 19:23:12 +02:00
Tim Ruffing
0a446a312f cmake: Add dev-mode CMake preset
To use, invoke `cmake` with argument `--preset dev-mode`.

Solves one item in #1235.

One disadvantage over `./configure --enable-dev-mode` is that CMake
does not provide a way to "hide" presets from users. That is,
`cmake --list-presets` will list dev-mode, and it will also appear
in `cmake-gui`, even though it's not selectable there due to bug
https://gitlab.kitware.com/cmake/cmake/-/issues/23341. (So in our
case, that's probably rather a feature than a bug.)

We curently use version 3 presets which require CMake 3.21+.
Unfortunately, CMake versions before 3.19 may ignore the `--preset`
argument silently. So if the preset is not picked up, make sure you
have a recent enough CMake version.

More unfortunately, we can't even spell this warning out in
CMakePresets.json because CMake does not support officially support
comments in JSON, see
 - https://gitlab.kitware.com/cmake/cmake/-/issues/21858
 - https://gitlab.kitware.com/cmake/cmake/-/merge_requests/5853 .
We could use a hack hinted at in
https://gitlab.kitware.com/cmake/cmake/-/issues/21858#note_908543
but that's risky, because it could simply break for future versions,
and we probably want to use presets not only for dev mode.
2023-04-20 19:22:43 +02:00
Tim Ruffing
a6f4bcf6e1 Merge bitcoin-core/secp256k1#1231: Move SECP256K1_INLINE macro definition out from include/secp256k1.h
8e142ca410 Move `SECP256K1_INLINE` macro definition out from `include/secp256k1.h` (Hennadii Stepanov)
77445898a5 Remove `SECP256K1_INLINE` usage from examples (Hennadii Stepanov)

Pull request description:

  From [IRC](https://gnusha.org/secp256k1/2023-01-31.log):
  > 06:29 \< hebasto\> What are reasons to define the `SECP256K1_INLINE` macro in user's `include/secp256k1.h` header, while it is used internally only?
  > 06:32 \< hebasto\> I mean, any other (or a new dedicated) header in `src` looks more appropriate, no?
  > 06:35 \< sipa\> I think it may just predate any "utility" internal headers.
  > 06:42 \< sipa\> I think it makes sense to move it to util.h

  Pros:
  - it is a step in direction to better organized headers (in context of #924, #1039)

  Cons:
  - code duplication for `SECP256K1_GNUC_PREREQ` macro

ACKs for top commit:
  sipa:
    utACK 8e142ca410
  real-or-random:
    utACK 8e142ca410

Tree-SHA512: 180e0ba7c2ef242b765f20698b67d06c492b7b70866c21db27c18d8b2e85c3e11f86c6cb99ffa88bbd23891ce3ee8a24bc528f2c91167ec2fddc167463f78eac
2023-04-20 18:18:11 +02:00
Hennadii Stepanov
a273d74b2e cmake: Improve version comparison 2023-04-20 17:03:42 +01:00
Hennadii Stepanov
6a58b483ef cmake: Use if(... IN_LIST ...) command
Available in CMake 3.3+.
2023-04-20 17:00:11 +01:00
Hennadii Stepanov
2445808c02 cmake: Use dedicated GENERATOR_IS_MULTI_CONFIG property
Available in CMake 3.9+.
2023-04-20 17:00:10 +01:00
Hennadii Stepanov
9f8703ef17 cmake: Use dedicated CMAKE_HOST_APPLE variable 2023-04-20 17:00:10 +01:00
Hennadii Stepanov
8c2017035a cmake: Use recommended add_compile_definitions command
Available in CMake 3.12+.
2023-04-20 17:00:10 +01:00
Hennadii Stepanov
04d4cc071a cmake: Add DESCRIPTION and HOMEPAGE_URL options to project command
`DESCRIPTION` is available in CMake 3.9+.
`HOMEPAGE_URL` is available in CMake 3.12+.
2023-04-20 17:00:10 +01:00
Hennadii Stepanov
8a8b6536ef cmake: Use SameMinorVersion compatibility mode
Available in CMake 3.11+.
2023-04-20 17:00:03 +01:00
Tim Ruffing
5b0444a3b5 Merge bitcoin-core/secp256k1#1263: cmake: Make installation optional
47ac3d63cd cmake: Make installation optional (Anna “CyberTailor”)

Pull request description:

  Useful for embedding secp256k1 in a subproject.

ACKs for top commit:
  theuni:
    ACK 47ac3d63cd.
  real-or-random:
    utACK 47ac3d63cd
  hebasto:
    ACK 47ac3d63cd, tested on Ubuntu 23.04.

Tree-SHA512: 12ac0ba9dc38adf45684055386280b669384b5a4e528a3f6f4470fd0b7f57d64dfed6a8bb9f0a84cacfcb72f509534d71676c5ba37b27297b1a96676eea44e6e
2023-04-20 17:44:44 +02:00
Anna “CyberTailor”
47ac3d63cd cmake: Make installation optional
Useful for embedding secp256k1 in a subproject.
2023-04-20 19:20:33 +05:00
Tim Ruffing
2e035af251 Merge bitcoin-core/secp256k1#1273: build: Make SECP_VALGRIND_CHECK preserve CPPFLAGS
1ecb94ebe9 build: Make `SECP_VALGRIND_CHECK` preserve `CPPFLAGS` (Hennadii Stepanov)

Pull request description:

  It was overlooked in #862 and #1027.

ACKs for top commit:
  real-or-random:
    utACK 1ecb94ebe9

Tree-SHA512: 263fc600ce9743e4aad767150f706bf7d4325dabb9c363ed57f08fe38faea94d7d1999804947cffeacbe698bb6d959ee6de3f6e50400050a390ecc0db957e426
2023-04-20 10:34:04 +02:00
Tim Ruffing
5be353d658 Merge bitcoin-core/secp256k1#1279: tests: lint wycheproof's python script
35ada3b954 tests: lint wycheproof's python script (RandomLattice)

Pull request description:

  This PR lints tests_wycheproof_generate.py according to bitcoin's python linting scripts. This is a follow-up to PR #1245.

ACKs for top commit:
  sipa:
    utACK 35ada3b954
  real-or-random:
    utACK 35ada3b954

Tree-SHA512: ea405060d2e73ff3543626687de5bc5282be923b914bd5c8c53e65df8dca9bea0000c416603095efff29bc7ae43c2081454c4e506db0f6805443d023fbffaf4c
2023-04-19 16:28:39 +02:00
Tim Ruffing
08f4b1632d autotools: Move code around to tidy Makefile 2023-04-19 15:55:25 +02:00
Tim Ruffing
04bf3f6778 Merge bitcoin-core/secp256k1#1230: Build: allow static or shared but not both
ef49a11d29 build: allow static or shared but not both (Cory Fields)
36b0adf1b9 build: remove warning until it's reproducible (Cory Fields)

Pull request description:

  Continuing from here: https://github.com/bitcoin-core/secp256k1/issues/1224#issuecomment-1460438227

  Unfortunately it wasn't really possible to keep a clean diff here because of the nature of the change. I suggest reviewing the lib creation stuff in its entirety, sorry about that :\

  Rather than allowing for shared and static libs to be built at the same time like autotools, this PR switches to the CMake convention of allowing only 1.

  A new `BUILD_SHARED_LIBS` option is added to match CMake convention, as well as a `SECP256K1_DISABLE_SHARED` option which overrides it. That way even projects which have `BUILD_SHARED_LIBS=1` can opt-into a static libsecp in particular.

  Details:

  Two object libraries are created: `secp256k1_asm` and `secp256k1_precomputed_objs`. Some tests/benchmarks use the object libraries directly, some link against the real lib: `secp256k1`.

  Because the objs don't know what they're going to be linked into, they need to be told how to deal with PIC.

  The `DEFINE_SYMBOL` property sets the `DLL_EXPORT` define as necessary (when building a shared lib)

ACKs for top commit:
  hebasto:
    re-ACK ef49a11d29, only [suggested](https://github.com/bitcoin-core/secp256k1/pull/1230#pullrequestreview-1388191165) changes since my recent [review](https://github.com/bitcoin-core/secp256k1/pull/1230#pullrequestreview-1352125381).
  real-or-random:
    ACK ef49a11d29

Tree-SHA512: 8870de305176fdb677caff0fdfc6f8c59c0e906489cb72bc9980e551002812685e59e20d731f2a82e33628bdfbb7261eafd6f228038cad3ec83bd74335959600
2023-04-18 12:54:03 +02:00
Tim Ruffing
9ce9984f32 Merge bitcoin-core/secp256k1#1265: Remove bits argument from secp256k1_wnaf_const{_xonly}
a575339c02 Remove bits argument from secp256k1_wnaf_const (always 256) (Pieter Wuille)

Pull request description:

  There is little reason for having the number of bits in the scalar as a parameter, as I don't think there are any (current) use cases for non-256-bit scalars.

ACKs for top commit:
  jonasnick:
    ACK a575339c02
  real-or-random:
    utACK a575339c02

Tree-SHA512: 994b1f19b4c513f6d070ed259a5d6f221a0c2450271ec824c5eba1cd0ecace276de391c170285bfeae96aaf8f1e0f7fe6260966ded0336c75c522ab6c56d182c
2023-04-18 12:25:09 +02:00
Jonas Nick
566faa17d3 Merge bitcoin-core/secp256k1#1267: doc: clarify process for patch releases
1b6fb5593c doc: clarify process for patch releases (Jonas Nick)

Pull request description:

ACKs for top commit:
  real-or-random:
    ACK 1b6fb5593c

Tree-SHA512: 5c1da34c920f66327b91c1fd11ad2eccbb55c5befdb3ba59138faf921ce83d0e7c62de84f2431b0a63433f1edc0f7f0f025a852a76dd3638e3fd583ca13b83e4
2023-04-18 08:19:51 +00:00
Cory Fields
ef49a11d29 build: allow static or shared but not both 2023-04-17 16:25:27 +00:00
RandomLattice
35ada3b954 tests: lint wycheproof's python script
This PR lints tests_wycheproof_generate.py according to pylint.
This is a follow-up to PR #1245.

Co-authored-by: Sean Andersen <6730974+andozw@users.noreply.github.com>
2023-04-14 18:59:35 +02:00
Tim Ruffing
4258c54f4e Merge bitcoin-core/secp256k1#1276: autotools: Don't regenerate Wycheproof header automatically
06c67dea9f autotools: Don't regenerate Wycheproof header automatically (Tim Ruffing)

Pull request description:

  This is a hot fix for https://github.com/bitcoin/bitcoin/pull/27445 .

  ---

  Pregenerated files that we distribute should not have dependencies in Makefile.am. For rationale, see the comments about the precomputed table files.

  See also https://github.com/bitcoin/bitcoin/pull/27445#issuecomment-1502994264 .

ACKs for top commit:
  hebasto:
    ACK 06c67dea9f
  RandomLattice:
    ACK 06c67dea9f

Tree-SHA512: fa7f44eaa1c7e42ecba5829ac1b8ae8b5826d1a1551e01c3caf37af780bd5c102c8f54e88520723937f7016d93c67b62a334c7a28b96c4f422a38fcf8e6a1984
2023-04-14 13:46:48 +02:00
Tim Ruffing
529b54d922 autotools: Move Wycheproof header from EXTRA_DIST to noinst_HEADERS 2023-04-14 08:00:10 +02:00
Tim Ruffing
06c67dea9f autotools: Don't regenerate Wycheproof header automatically
Pregenerated files that we distribute should not have dependencies
in Makefile.am. For rationale, see the comments about the precomputed
table files.

See also https://github.com/bitcoin/bitcoin/pull/27445#issuecomment-1502994264 .
2023-04-14 07:59:57 +02:00
Hennadii Stepanov
dc0657c762 build: Fix C4005 "macro redefinition" MSVC warnings in examples 2023-04-13 12:23:30 +01:00
Hennadii Stepanov
1ecb94ebe9 build: Make SECP_VALGRIND_CHECK preserve CPPFLAGS 2023-04-11 18:59:12 +01:00
Jonas Nick
3bab71cf05 Merge bitcoin-core/secp256k1#1268: release cleanup: bump version after 0.3.1
656c6ea8d8 release cleanup: bump version after 0.3.1 (Jonas Nick)

Pull request description:

ACKs for top commit:
  sipa:
    ACK 656c6ea8d8
  real-or-random:
    ACK 656c6ea8d8

Tree-SHA512: da24326ed5feaa6a432522bddd64e6c129455cfe55a9e2decfce8c6039f4ce1a1da64233d17200f45d2c142f5414505b9a9b2ef5d136e047c1dd6cfdde1b560d
2023-04-10 20:05:59 +00:00
Jonas Nick
656c6ea8d8 release cleanup: bump version after 0.3.1 2023-04-10 19:50:27 +00:00
Jonas Nick
1b6fb5593c doc: clarify process for patch releases 2023-04-10 15:19:07 +00:00
Pieter Wuille
a575339c02 Remove bits argument from secp256k1_wnaf_const (always 256) 2023-04-10 06:40:21 -04:00
Cory Fields
36b0adf1b9 build: remove warning until it's reproducible
Also remove the interface it was attached to since it's no longer needed.
This removal simplifies the next commit.
2023-03-21 16:21:21 +00:00
Hennadii Stepanov
8e142ca410 Move SECP256K1_INLINE macro definition out from include/secp256k1.h 2023-03-09 15:29:56 +00:00
Hennadii Stepanov
77445898a5 Remove SECP256K1_INLINE usage from examples 2023-03-09 13:05:14 +00:00
Tim Ruffing
ca92a35d01 field: Simplify code in secp256k1_fe_set_b32 2023-02-01 12:29:34 +01:00
Tim Ruffing
d93f62e369 field: Verify field element even after secp256k1_fe_set_b32 fails 2023-02-01 12:29:03 +01:00
62 changed files with 1668 additions and 1025 deletions

View File

@@ -176,7 +176,7 @@ task:
CTIMETESTS: no
matrix:
- env: {}
- env: {EXPERIMENTAL: yes, ASM: arm}
- env: {EXPERIMENTAL: yes, ASM: arm32}
<< : *MERGE_BASE
test_script:
- ./ci/cirrus.sh
@@ -397,13 +397,13 @@ task:
- PowerShell -NoLogo -Command if ($env:CIRRUS_PR -ne $null) { git fetch $env:CIRRUS_REPO_CLONE_URL pull/$env:CIRRUS_PR/merge; git reset --hard FETCH_HEAD; }
configure_script:
- '%x64_NATIVE_TOOLS%'
- cmake -G "Visual Studio 17 2022" -A x64 -S . -B build -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DSECP256K1_BUILD_EXAMPLES=ON
- cmake -E env CFLAGS="/WX" cmake -G "Visual Studio 17 2022" -A x64 -S . -B build -DSECP256K1_ENABLE_MODULE_RECOVERY=ON -DSECP256K1_BUILD_EXAMPLES=ON
build_script:
- '%x64_NATIVE_TOOLS%'
- cmake --build build --config RelWithDebInfo -- -property:UseMultiToolTask=true;CL_MPcount=5
check_script:
- '%x64_NATIVE_TOOLS%'
- ctest --test-dir build -j 5
- ctest -C RelWithDebInfo --test-dir build -j 5
- build\src\RelWithDebInfo\bench_ecmult.exe
- build\src\RelWithDebInfo\bench_internal.exe
- build\src\RelWithDebInfo\bench.exe

2
.gitignore vendored
View File

@@ -59,5 +59,7 @@ build-aux/compile
build-aux/test-driver
libsecp256k1.pc
### CMake
/CMakeUserPresets.json
# Default CMake build directory.
/build

View File

@@ -5,6 +5,25 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.3.2] - 2023-05-13
We strongly recommend updating to 0.3.2 if you use or plan to use GCC >=13 to compile libsecp256k1. When in doubt, check the GCC version using `gcc -v`.
#### Security
- Module `ecdh`: Fix "constant-timeness" issue with GCC 13.1 (and potentially future versions of GCC) that could leave applications using libsecp256k1's ECDH module vulnerable to a timing side-channel attack. The fix avoids secret-dependent control flow during ECDH computations when libsecp256k1 is compiled with GCC 13.1.
#### Fixed
- Fixed an old bug that permitted compilers to potentially output bad assembly code on x86_64. In theory, it could lead to a crash or a read of unrelated memory, but this has never been observed on any compilers so far.
#### Changed
- Various improvements and changes to CMake builds. CMake builds remain experimental.
- Made API versioning consistent with GNU Autotools builds.
- Switched to `BUILD_SHARED_LIBS` variable for controlling whether to build a static or a shared library.
- Added `SECP256K1_INSTALL` variable for the controlling whether to install the build artefacts.
- Renamed asm build option `arm` to `arm32`. Use `--with-asm=arm32` instead of `--with-asm=arm` (GNU Autotools), and `-DSECP256K1_ASM=arm32` instead of `-DSECP256K1_ASM=arm` (CMake).
#### ABI Compatibility
The ABI is compatible with versions 0.3.0 and 0.3.1.
## [0.3.1] - 2023-04-10
We strongly recommend updating to 0.3.1 if you use or plan to use Clang >=14 to compile libsecp256k1, e.g., Xcode >=14 on macOS has Clang >=14. When in doubt, check the Clang version using `clang -v`.
@@ -66,7 +85,8 @@ This version was in fact never released.
The number was given by the build system since the introduction of autotools in Jan 2014 (ea0fe5a5bf0c04f9cc955b2966b614f5f378c6f6).
Therefore, this version number does not uniquely identify a set of source files.
[unreleased]: https://github.com/bitcoin-core/secp256k1/compare/v0.3.0...HEAD
[unreleased]: https://github.com/bitcoin-core/secp256k1/compare/v0.3.2...HEAD
[0.3.2]: https://github.com/bitcoin-core/secp256k1/compare/v0.3.1...v0.3.2
[0.3.1]: https://github.com/bitcoin-core/secp256k1/compare/v0.3.0...v0.3.1
[0.3.0]: https://github.com/bitcoin-core/secp256k1/compare/v0.2.0...v0.3.0
[0.2.0]: https://github.com/bitcoin-core/secp256k1/compare/423b6d19d373f1224fd671a982584d7e7900bc93..v0.2.0

View File

@@ -1,16 +1,33 @@
cmake_minimum_required(VERSION 3.13)
if(CMAKE_VERSION VERSION_GREATER 3.14)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.15)
# MSVC runtime library flags are selected by the CMAKE_MSVC_RUNTIME_LIBRARY abstraction.
cmake_policy(SET CMP0091 NEW)
# MSVC warning flags are not in CMAKE_<LANG>_FLAGS by default.
cmake_policy(SET CMP0092 NEW)
endif()
# The package (a.k.a. release) version is based on semantic versioning 2.0.0 of
# the API. All changes in experimental modules are treated as
# backwards-compatible and therefore at most increase the minor version.
project(libsecp256k1 VERSION 0.3.1 LANGUAGES C)
project(libsecp256k1
# The package (a.k.a. release) version is based on semantic versioning 2.0.0 of
# the API. All changes in experimental modules are treated as
# backwards-compatible and therefore at most increase the minor version.
VERSION 0.3.2
DESCRIPTION "Optimized C library for ECDSA signatures and secret/public key operations on curve secp256k1."
HOMEPAGE_URL "https://github.com/bitcoin-core/secp256k1"
LANGUAGES C
)
if(CMAKE_VERSION VERSION_LESS 3.21)
get_directory_property(parent_directory PARENT_DIRECTORY)
if(parent_directory)
set(PROJECT_IS_TOP_LEVEL OFF CACHE INTERNAL "Emulates CMake 3.21+ behavior.")
set(${PROJECT_NAME}_IS_TOP_LEVEL OFF CACHE INTERNAL "Emulates CMake 3.21+ behavior.")
else()
set(PROJECT_IS_TOP_LEVEL ON CACHE INTERNAL "Emulates CMake 3.21+ behavior.")
set(${PROJECT_NAME}_IS_TOP_LEVEL ON CACHE INTERNAL "Emulates CMake 3.21+ behavior.")
endif()
unset(parent_directory)
endif()
# The library version is based on libtool versioning of the ABI. The set of
# rules for updating the version can be found here:
@@ -18,7 +35,7 @@ project(libsecp256k1 VERSION 0.3.1 LANGUAGES C)
# All changes in experimental modules are treated as if they don't affect the
# interface and therefore only increase the revision.
set(${PROJECT_NAME}_LIB_VERSION_CURRENT 2)
set(${PROJECT_NAME}_LIB_VERSION_REVISION 1)
set(${PROJECT_NAME}_LIB_VERSION_REVISION 2)
set(${PROJECT_NAME}_LIB_VERSION_AGE 0)
set(CMAKE_C_STANDARD 90)
@@ -26,36 +43,37 @@ set(CMAKE_C_EXTENSIONS OFF)
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
# We do not use CMake's BUILD_SHARED_LIBS option.
option(SECP256K1_BUILD_SHARED "Build shared library." ON)
option(SECP256K1_BUILD_STATIC "Build static library." ON)
if(NOT SECP256K1_BUILD_SHARED AND NOT SECP256K1_BUILD_STATIC)
message(FATAL_ERROR "At least one of SECP256K1_BUILD_SHARED and SECP256K1_BUILD_STATIC must be enabled.")
option(BUILD_SHARED_LIBS "Build shared libraries." ON)
option(SECP256K1_DISABLE_SHARED "Disable shared library. Overrides BUILD_SHARED_LIBS." OFF)
if(SECP256K1_DISABLE_SHARED)
set(BUILD_SHARED_LIBS OFF)
endif()
option(SECP256K1_INSTALL "Enable installation." ${PROJECT_IS_TOP_LEVEL})
option(SECP256K1_ENABLE_MODULE_ECDH "Enable ECDH module." ON)
if(SECP256K1_ENABLE_MODULE_ECDH)
add_definitions(-DENABLE_MODULE_ECDH=1)
add_compile_definitions(ENABLE_MODULE_ECDH=1)
endif()
option(SECP256K1_ENABLE_MODULE_RECOVERY "Enable ECDSA pubkey recovery module." OFF)
if(SECP256K1_ENABLE_MODULE_RECOVERY)
add_definitions(-DENABLE_MODULE_RECOVERY=1)
add_compile_definitions(ENABLE_MODULE_RECOVERY=1)
endif()
option(SECP256K1_ENABLE_MODULE_EXTRAKEYS "Enable extrakeys module." ON)
option(SECP256K1_ENABLE_MODULE_SCHNORRSIG "Enable schnorrsig module." ON)
if(SECP256K1_ENABLE_MODULE_SCHNORRSIG)
set(SECP256K1_ENABLE_MODULE_EXTRAKEYS ON)
add_definitions(-DENABLE_MODULE_SCHNORRSIG=1)
add_compile_definitions(ENABLE_MODULE_SCHNORRSIG=1)
endif()
if(SECP256K1_ENABLE_MODULE_EXTRAKEYS)
add_definitions(-DENABLE_MODULE_EXTRAKEYS=1)
add_compile_definitions(ENABLE_MODULE_EXTRAKEYS=1)
endif()
option(SECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS "Enable external default callback functions." OFF)
if(SECP256K1_USE_EXTERNAL_DEFAULT_CALLBACKS)
add_definitions(-DUSE_EXTERNAL_DEFAULT_CALLBACKS=1)
add_compile_definitions(USE_EXTERNAL_DEFAULT_CALLBACKS=1)
endif()
set(SECP256K1_ECMULT_WINDOW_SIZE "AUTO" CACHE STRING "Window size for ecmult precomputation for verification, specified as integer in range [2..24]. \"AUTO\" is a reasonable setting for desktop machines (currently 15). [default=AUTO]")
@@ -65,7 +83,7 @@ check_string_option_value(SECP256K1_ECMULT_WINDOW_SIZE)
if(SECP256K1_ECMULT_WINDOW_SIZE STREQUAL "AUTO")
set(SECP256K1_ECMULT_WINDOW_SIZE 15)
endif()
add_definitions(-DECMULT_WINDOW_SIZE=${SECP256K1_ECMULT_WINDOW_SIZE})
add_compile_definitions(ECMULT_WINDOW_SIZE=${SECP256K1_ECMULT_WINDOW_SIZE})
set(SECP256K1_ECMULT_GEN_PREC_BITS "AUTO" CACHE STRING "Precision bits to tune the precomputed table size for signing, specified as integer 2, 4 or 8. \"AUTO\" is a reasonable setting for desktop machines (currently 4). [default=AUTO]")
set_property(CACHE SECP256K1_ECMULT_GEN_PREC_BITS PROPERTY STRINGS "AUTO" 2 4 8)
@@ -73,29 +91,35 @@ check_string_option_value(SECP256K1_ECMULT_GEN_PREC_BITS)
if(SECP256K1_ECMULT_GEN_PREC_BITS STREQUAL "AUTO")
set(SECP256K1_ECMULT_GEN_PREC_BITS 4)
endif()
add_definitions(-DECMULT_GEN_PREC_BITS=${SECP256K1_ECMULT_GEN_PREC_BITS})
add_compile_definitions(ECMULT_GEN_PREC_BITS=${SECP256K1_ECMULT_GEN_PREC_BITS})
set(SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY "OFF" CACHE STRING "Test-only override of the (autodetected by the C code) \"widemul\" setting. Legal values are: \"OFF\", \"int128_struct\", \"int128\" or \"int64\". [default=OFF]")
set_property(CACHE SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY PROPERTY STRINGS "OFF" "int128_struct" "int128" "int64")
check_string_option_value(SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY)
if(SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY)
string(TOUPPER "${SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY}" widemul_upper_value)
add_definitions(-DUSE_FORCE_WIDEMUL_${widemul_upper_value}=1)
add_compile_definitions(USE_FORCE_WIDEMUL_${widemul_upper_value}=1)
endif()
mark_as_advanced(FORCE SECP256K1_TEST_OVERRIDE_WIDE_MULTIPLY)
set(SECP256K1_ASM "AUTO" CACHE STRING "Assembly optimizations to use: \"AUTO\", \"OFF\", \"x86_64\" or \"arm\" (experimental). [default=AUTO]")
set_property(CACHE SECP256K1_ASM PROPERTY STRINGS "AUTO" "OFF" "x86_64" "arm")
set(SECP256K1_ASM "AUTO" CACHE STRING "Assembly optimizations to use: \"AUTO\", \"OFF\", \"x86_64\" or \"arm32\" (experimental). [default=AUTO]")
set_property(CACHE SECP256K1_ASM PROPERTY STRINGS "AUTO" "OFF" "x86_64" "arm32")
check_string_option_value(SECP256K1_ASM)
if(SECP256K1_ASM STREQUAL "arm")
if(SECP256K1_ASM STREQUAL "arm32")
enable_language(ASM)
add_definitions(-DUSE_EXTERNAL_ASM=1)
include(CheckArm32Assembly)
check_arm32_assembly()
if(HAVE_ARM32_ASM)
add_compile_definitions(USE_EXTERNAL_ASM=1)
else()
message(FATAL_ERROR "ARM32 assembly optimization requested but not available.")
endif()
elseif(SECP256K1_ASM)
include(Check64bitAssembly)
check_64bit_assembly()
if(HAS_64BIT_ASM)
include(CheckX86_64Assembly)
check_x86_64_assembly()
if(HAVE_X86_64_ASM)
set(SECP256K1_ASM "x86_64")
add_definitions(-DUSE_ASM_X86_64=1)
add_compile_definitions(USE_ASM_X86_64=1)
elseif(SECP256K1_ASM STREQUAL "AUTO")
set(SECP256K1_ASM "OFF")
else()
@@ -105,8 +129,8 @@ endif()
option(SECP256K1_EXPERIMENTAL "Allow experimental configuration options." OFF)
if(NOT SECP256K1_EXPERIMENTAL)
if(SECP256K1_ASM STREQUAL "arm")
message(FATAL_ERROR "ARM assembly optimization is experimental. Use -DSECP256K1_EXPERIMENTAL=ON to allow.")
if(SECP256K1_ASM STREQUAL "arm32")
message(FATAL_ERROR "ARM32 assembly optimization is experimental. Use -DSECP256K1_EXPERIMENTAL=ON to allow.")
endif()
endif()
@@ -118,7 +142,7 @@ if(SECP256K1_VALGRIND)
if(Valgrind_FOUND)
set(SECP256K1_VALGRIND ON)
include_directories(${Valgrind_INCLUDE_DIR})
add_definitions(-DVALGRIND)
add_compile_definitions(VALGRIND)
elseif(SECP256K1_VALGRIND STREQUAL "AUTO")
set(SECP256K1_VALGRIND OFF)
else()
@@ -165,42 +189,47 @@ mark_as_advanced(
CMAKE_SHARED_LINKER_FLAGS_COVERAGE
)
if(CMAKE_CONFIGURATION_TYPES)
set(CMAKE_CONFIGURATION_TYPES "RelWithDebInfo" "Release" "Debug" "MinSizeRel" "Coverage")
endif()
get_property(cached_cmake_build_type CACHE CMAKE_BUILD_TYPE PROPERTY TYPE)
if(cached_cmake_build_type)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY
STRINGS "RelWithDebInfo" "Release" "Debug" "MinSizeRel" "Coverage"
)
endif()
get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
set(default_build_type "RelWithDebInfo")
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to \"${default_build_type}\" as none was specified")
set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build." FORCE)
if(is_multi_config)
set(CMAKE_CONFIGURATION_TYPES "${default_build_type}" "Release" "Debug" "MinSizeRel" "Coverage" CACHE STRING
"Supported configuration types."
FORCE
)
else()
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY
STRINGS "${default_build_type}" "Release" "Debug" "MinSizeRel" "Coverage"
)
if(NOT CMAKE_BUILD_TYPE)
message(STATUS "Setting build type to \"${default_build_type}\" as none was specified")
set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING
"Choose the type of build."
FORCE
)
endif()
endif()
include(TryAddCompileOption)
include(TryAppendCFlags)
if(MSVC)
try_add_compile_option(/W2)
try_add_compile_option(/wd4146)
# Keep the following commands ordered lexicographically.
try_append_c_flags(/W2) # Moderate warning level.
try_append_c_flags(/wd4146) # Disable warning C4146 "unary minus operator applied to unsigned type, result still unsigned".
else()
try_add_compile_option(-pedantic)
try_add_compile_option(-Wall)
try_add_compile_option(-Wcast-align)
try_add_compile_option(-Wcast-align=strict)
try_add_compile_option(-Wconditional-uninitialized)
try_add_compile_option(-Wextra)
try_add_compile_option(-Wnested-externs)
try_add_compile_option(-Wno-long-long)
try_add_compile_option(-Wno-overlength-strings)
try_add_compile_option(-Wno-unused-function)
try_add_compile_option(-Wreserved-identifier)
try_add_compile_option(-Wshadow)
try_add_compile_option(-Wstrict-prototypes)
try_add_compile_option(-Wundef)
# Keep the following commands ordered lexicographically.
try_append_c_flags(-pedantic)
try_append_c_flags(-Wall) # GCC >= 2.95 and probably many other compilers.
try_append_c_flags(-Wcast-align) # GCC >= 2.95.
try_append_c_flags(-Wcast-align=strict) # GCC >= 8.0.
try_append_c_flags(-Wconditional-uninitialized) # Clang >= 3.0 only.
try_append_c_flags(-Wextra) # GCC >= 3.4, this is the newer name of -W, which we don't use because older GCCs will warn about unused functions.
try_append_c_flags(-Wnested-externs)
try_append_c_flags(-Wno-long-long) # GCC >= 3.0, -Wlong-long is implied by -pedantic.
try_append_c_flags(-Wno-overlength-strings) # GCC >= 4.2, -Woverlength-strings is implied by -pedantic.
try_append_c_flags(-Wno-unused-function) # GCC >= 3.0, -Wunused-function is implied by -Wall.
try_append_c_flags(-Wreserved-identifier) # Clang >= 13.0 only.
try_append_c_flags(-Wshadow)
try_append_c_flags(-Wstrict-prototypes)
try_append_c_flags(-Wundef)
endif()
set(CMAKE_C_VISIBILITY_PRESET hidden)
@@ -225,8 +254,13 @@ message("\n")
message("secp256k1 configure summary")
message("===========================")
message("Build artifacts:")
message(" shared library ...................... ${SECP256K1_BUILD_SHARED}")
message(" static library ...................... ${SECP256K1_BUILD_STATIC}")
if(BUILD_SHARED_LIBS)
set(library_type "Shared")
else()
set(library_type "Static")
endif()
message(" library type ........................ ${library_type}")
message("Optional modules:")
message(" ECDH ................................ ${SECP256K1_ENABLE_MODULE_ECDH}")
message(" ECDSA pubkey recovery ............... ${SECP256K1_ENABLE_MODULE_RECOVERY}")
@@ -268,7 +302,7 @@ message("CFLAGS ................................ ${CMAKE_C_FLAGS}")
get_directory_property(compile_options COMPILE_OPTIONS)
string(REPLACE ";" " " compile_options "${compile_options}")
message("Compile options ....................... " ${compile_options})
if(DEFINED CMAKE_BUILD_TYPE)
if(NOT is_multi_config)
message("Build type:")
message(" - CMAKE_BUILD_TYPE ................... ${CMAKE_BUILD_TYPE}")
string(TOUPPER "${CMAKE_BUILD_TYPE}" build_type)
@@ -276,7 +310,7 @@ if(DEFINED CMAKE_BUILD_TYPE)
message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_${build_type}}")
message(" - LDFLAGS for shared libraries ....... ${CMAKE_SHARED_LINKER_FLAGS_${build_type}}")
else()
message("Available configurations .............. ${CMAKE_CONFIGURATION_TYPES}")
message("Supported configurations .............. ${CMAKE_CONFIGURATION_TYPES}")
message("RelWithDebInfo configuration:")
message(" - CFLAGS ............................. ${CMAKE_C_FLAGS_RELWITHDEBINFO}")
message(" - LDFLAGS for executables ............ ${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}")

19
CMakePresets.json Normal file
View File

@@ -0,0 +1,19 @@
{
"cmakeMinimumRequired": {"major": 3, "minor": 21, "patch": 0},
"version": 3,
"configurePresets": [
{
"name": "dev-mode",
"displayName": "Development mode (intended only for developers of the library)",
"cacheVariables": {
"SECP256K1_EXPERIMENTAL": "ON",
"SECP256K1_ENABLE_MODULE_RECOVERY": "ON",
"SECP256K1_BUILD_EXAMPLES": "ON"
},
"warnings": {
"dev": true,
"uninitialized": true
}
}
]
}

View File

@@ -1,5 +1,3 @@
.PHONY: clean-precomp precomp
ACLOCAL_AMFLAGS = -I build-aux/m4
# AM_CFLAGS will be automatically prepended to CFLAGS by Automake when compiling some foo
@@ -65,6 +63,7 @@ noinst_HEADERS += src/hash_impl.h
noinst_HEADERS += src/field.h
noinst_HEADERS += src/field_impl.h
noinst_HEADERS += src/bench.h
noinst_HEADERS += src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h
noinst_HEADERS += contrib/lax_der_parsing.h
noinst_HEADERS += contrib/lax_der_parsing.c
noinst_HEADERS += contrib/lax_der_privatekey_parsing.h
@@ -202,7 +201,7 @@ precompute_ecmult_gen_LDADD = $(COMMON_LIB)
# otherwise make's decision whether to rebuild them (even in the first
# build by a normal user) depends on mtimes, and thus is very fragile.
# This means that rebuilds of the prebuilt files always need to be
# forced by deleting them, e.g., by invoking `make clean-precomp`.
# forced by deleting them.
src/precomputed_ecmult.c:
$(MAKE) $(AM_MAKEFLAGS) precompute_ecmult$(EXEEXT)
./precompute_ecmult$(EXEEXT)
@@ -217,11 +216,29 @@ precomp: $(PRECOMP)
# e.g., after `make maintainer-clean`).
BUILT_SOURCES = $(PRECOMP)
maintainer-clean-local: clean-precomp
.PHONY: clean-precomp
clean-precomp:
rm -f $(PRECOMP)
maintainer-clean-local: clean-precomp
### Pregenerated test vectors
### (see the comments in the previous section for detailed rationale)
TESTVECTORS = src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h
src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h:
mkdir -p $(@D)
python3 $(top_srcdir)/tools/tests_wycheproof_generate.py $(top_srcdir)/src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json > $@
testvectors: $(TESTVECTORS)
BUILT_SOURCES += $(TESTVECTORS)
.PHONY: clean-testvectors
clean-testvectors:
rm -f $(TESTVECTORS)
maintainer-clean-local: clean-testvectors
### Additional files to distribute
EXTRA_DIST = autogen.sh CHANGELOG.md SECURITY.md
EXTRA_DIST += doc/release-process.md doc/safegcd_implementation.md
EXTRA_DIST += examples/EXAMPLES_COPYING
@@ -231,6 +248,9 @@ EXTRA_DIST += sage/group_prover.sage
EXTRA_DIST += sage/prove_group_implementations.sage
EXTRA_DIST += sage/secp256k1_params.sage
EXTRA_DIST += sage/weierstrass_prover.sage
EXTRA_DIST += src/wycheproof/WYCHEPROOF_COPYING
EXTRA_DIST += src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json
EXTRA_DIST += tools/tests_wycheproof_generate.py
if ENABLE_MODULE_ECDH
include src/modules/ecdh/Makefile.am.include
@@ -247,20 +267,3 @@ endif
if ENABLE_MODULE_SCHNORRSIG
include src/modules/schnorrsig/Makefile.am.include
endif
EXTRA_DIST += src/wycheproof/WYCHEPROOF_COPYING
EXTRA_DIST += src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h
EXTRA_DIST += src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json
EXTRA_DIST += tools/tests_wycheproof_generate.py
TESTVECTORS = src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h
src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.h: src/wycheproof/ecdsa_secp256k1_sha256_bitcoin_test.json
python3 tools/tests_wycheproof_generate.py $< > $@
testvectors: $(TESTVECTORS)
maintainer-clean-testvectors: clean-testvectors
clean-testvectors:
rm -f $(TESTVECTORS)

View File

@@ -1,12 +1,31 @@
dnl escape "$0x" below using the m4 quadrigaph @S|@, and escape it again with a \ for the shell.
AC_DEFUN([SECP_64BIT_ASM_CHECK],[
AC_DEFUN([SECP_X86_64_ASM_CHECK],[
AC_MSG_CHECKING(for x86_64 assembly availability)
AC_LINK_IFELSE([AC_LANG_PROGRAM([[
#include <stdint.h>]],[[
uint64_t a = 11, tmp;
__asm__ __volatile__("movq \@S|@0x100000000,%1; mulq %%rsi" : "+a"(a) : "S"(tmp) : "cc", "%rdx");
]])],[has_64bit_asm=yes],[has_64bit_asm=no])
AC_MSG_RESULT([$has_64bit_asm])
]])], [has_x86_64_asm=yes], [has_x86_64_asm=no])
AC_MSG_RESULT([$has_x86_64_asm])
])
AC_DEFUN([SECP_ARM32_ASM_CHECK], [
AC_MSG_CHECKING(for ARM32 assembly availability)
SECP_ARM32_ASM_CHECK_CFLAGS_saved_CFLAGS="$CFLAGS"
CFLAGS="-x assembler"
AC_LINK_IFELSE([AC_LANG_SOURCE([[
.syntax unified
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.text
.global main
main:
ldr r0, =0x002A
mov r7, #1
swi 0
]])], [has_arm32_asm=yes], [has_arm32_asm=no])
AC_MSG_RESULT([$has_arm32_asm])
CFLAGS="$SECP_ARM32_ASM_CHECK_CFLAGS_saved_CFLAGS"
])
AC_DEFUN([SECP_VALGRIND_CHECK],[
@@ -21,6 +40,7 @@ if test x"$has_valgrind" != x"yes"; then
# error "Valgrind does not support this platform."
#endif
]])], [has_valgrind=yes])
CPPFLAGS="$CPPFLAGS_TEMP"
fi
AC_MSG_RESULT($has_valgrind)
])

View File

@@ -0,0 +1,6 @@
function(check_arm32_assembly)
try_compile(HAVE_ARM32_ASM
${CMAKE_BINARY_DIR}/check_arm32_assembly
SOURCES ${CMAKE_SOURCE_DIR}/cmake/source_arm32.s
)
endfunction()

View File

@@ -1,11 +1,9 @@
function(check_string_option_value option)
get_property(expected_values CACHE ${option} PROPERTY STRINGS)
if(expected_values)
foreach(value IN LISTS expected_values)
if(value STREQUAL "${${option}}")
return()
endif()
endforeach()
if(${option} IN_LIST expected_values)
return()
endif()
message(FATAL_ERROR "${option} value is \"${${option}}\", but must be one of ${expected_values}.")
endif()
message(AUTHOR_WARNING "The STRINGS property must be set before invoking `check_string_option_value' function.")

View File

@@ -1,6 +1,6 @@
include(CheckCSourceCompiles)
function(check_64bit_assembly)
function(check_x86_64_assembly)
check_c_source_compiles("
#include <stdint.h>
@@ -9,6 +9,6 @@ function(check_64bit_assembly)
uint64_t a = 11, tmp;
__asm__ __volatile__(\"movq $0x100000000,%1; mulq %%rsi\" : \"+a\"(a) : \"S\"(tmp) : \"cc\", \"%rdx\");
}
" HAS_64BIT_ASM)
set(HAS_64BIT_ASM ${HAS_64BIT_ASM} PARENT_SCOPE)
" HAVE_X86_64_ASM)
set(HAVE_X86_64_ASM ${HAVE_X86_64_ASM} PARENT_SCOPE)
endfunction()

View File

@@ -1,4 +1,4 @@
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
if(CMAKE_HOST_APPLE)
find_program(BREW_COMMAND brew)
execute_process(
COMMAND ${BREW_COMMAND} --prefix valgrind

View File

@@ -1,23 +0,0 @@
include(CheckCCompilerFlag)
function(try_add_compile_option option)
string(MAKE_C_IDENTIFIER ${option} result)
string(TOUPPER ${result} result)
set(result "C_SUPPORTS${result}")
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
if(NOT MSVC)
set(CMAKE_REQUIRED_FLAGS "-Werror")
endif()
check_c_compiler_flag(${option} ${result})
if(${result})
get_property(compile_options
DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
PROPERTY COMPILE_OPTIONS
)
list(APPEND compile_options "${option}")
set_property(
DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
PROPERTY COMPILE_OPTIONS "${compile_options}"
)
endif()
endfunction()

View File

@@ -0,0 +1,24 @@
include(CheckCCompilerFlag)
function(secp256k1_check_c_flags_internal flags output)
string(MAKE_C_IDENTIFIER "${flags}" result)
string(TOUPPER "${result}" result)
set(result "C_SUPPORTS_${result}")
if(NOT MSVC)
set(CMAKE_REQUIRED_FLAGS "-Werror")
endif()
# This avoids running a linker.
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
check_c_compiler_flag("${flags}" ${result})
set(${output} ${${result}} PARENT_SCOPE)
endfunction()
# Append flags to the COMPILE_OPTIONS directory property if CC accepts them.
macro(try_append_c_flags)
secp256k1_check_c_flags_internal("${ARGV}" result)
if(result)
add_compile_options(${ARGV})
endif()
endmacro()

9
cmake/source_arm32.s Normal file
View File

@@ -0,0 +1,9 @@
.syntax unified
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.text
.global main
main:
ldr r0, =0x002A
mov r7, #1
swi 0

View File

@@ -5,7 +5,7 @@ AC_PREREQ([2.60])
# backwards-compatible and therefore at most increase the minor version.
define(_PKG_VERSION_MAJOR, 0)
define(_PKG_VERSION_MINOR, 3)
define(_PKG_VERSION_PATCH, 1)
define(_PKG_VERSION_PATCH, 2)
define(_PKG_VERSION_IS_RELEASE, true)
# The library version is based on libtool versioning of the ABI. The set of
@@ -14,7 +14,7 @@ define(_PKG_VERSION_IS_RELEASE, true)
# All changes in experimental modules are treated as if they don't affect the
# interface and therefore only increase the revision.
define(_LIB_VERSION_CURRENT, 2)
define(_LIB_VERSION_REVISION, 1)
define(_LIB_VERSION_REVISION, 2)
define(_LIB_VERSION_AGE, 0)
AC_INIT([libsecp256k1],m4_join([.], _PKG_VERSION_MAJOR, _PKG_VERSION_MINOR, _PKG_VERSION_PATCH)m4_if(_PKG_VERSION_IS_RELEASE, [true], [], [-dev]),[https://github.com/bitcoin-core/secp256k1/issues],[libsecp256k1],[https://github.com/bitcoin-core/secp256k1])
@@ -122,7 +122,6 @@ AC_DEFUN([SECP_TRY_APPEND_DEFAULT_CFLAGS], [
# Note that "/opt" and "-opt" are equivalent for MSVC; we use "-opt" because "/opt" looks like a path.
if test x"$GCC" != x"yes" && test x"$build_windows" = x"yes"; then
SECP_TRY_APPEND_CFLAGS([-W2 -wd4146], $1) # Moderate warning level, disable warning C4146 "unary minus operator applied to unsigned type, result still unsigned"
SECP_TRY_APPEND_CFLAGS([-external:anglebrackets -external:W0], $1) # Suppress warnings from #include <...> files
# We pass -ignore:4217 to the MSVC linker to suppress warning 4217 when
# importing variables from a statically linked secp256k1.
# (See the libtool manual, section "Windows DLLs" for background.)
@@ -198,8 +197,8 @@ AC_ARG_ENABLE(external_default_callbacks,
# * and auto (the default).
AC_ARG_WITH([test-override-wide-multiply], [] ,[set_widemul=$withval], [set_widemul=auto])
AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|arm|no|auto],
[assembly optimizations to use (experimental: arm) [default=auto]])],[req_asm=$withval], [req_asm=auto])
AC_ARG_WITH([asm], [AS_HELP_STRING([--with-asm=x86_64|arm32|no|auto],
[assembly optimizations to use (experimental: arm32) [default=auto]])],[req_asm=$withval], [req_asm=auto])
AC_ARG_WITH([ecmult-window], [AS_HELP_STRING([--with-ecmult-window=SIZE|auto],
[window size for ecmult precomputation for verification, specified as integer in range [2..24].]
@@ -264,8 +263,8 @@ else
fi
if test x"$req_asm" = x"auto"; then
SECP_64BIT_ASM_CHECK
if test x"$has_64bit_asm" = x"yes"; then
SECP_X86_64_ASM_CHECK
if test x"$has_x86_64_asm" = x"yes"; then
set_asm=x86_64
fi
if test x"$set_asm" = x; then
@@ -275,12 +274,16 @@ else
set_asm=$req_asm
case $set_asm in
x86_64)
SECP_64BIT_ASM_CHECK
if test x"$has_64bit_asm" != x"yes"; then
SECP_X86_64_ASM_CHECK
if test x"$has_x86_64_asm" != x"yes"; then
AC_MSG_ERROR([x86_64 assembly optimization requested but not available])
fi
;;
arm)
arm32)
SECP_ARM32_ASM_CHECK
if test x"$has_arm32_asm" != x"yes"; then
AC_MSG_ERROR([ARM32 assembly optimization requested but not available])
fi
;;
no)
;;
@@ -297,7 +300,7 @@ case $set_asm in
x86_64)
SECP_CONFIG_DEFINES="$SECP_CONFIG_DEFINES -DUSE_ASM_X86_64=1"
;;
arm)
arm32)
enable_external_asm=yes
;;
no)
@@ -414,8 +417,8 @@ if test x"$enable_experimental" = x"yes"; then
AC_MSG_NOTICE([Experimental features do not have stable APIs or properties, and may not be safe for production use.])
AC_MSG_NOTICE([******])
else
if test x"$set_asm" = x"arm"; then
AC_MSG_ERROR([ARM assembly optimization is experimental. Use --enable-experimental to allow.])
if test x"$set_asm" = x"arm32"; then
AC_MSG_ERROR([ARM32 assembly optimization is experimental. Use --enable-experimental to allow.])
fi
fi
@@ -437,7 +440,7 @@ AM_CONDITIONAL([ENABLE_MODULE_RECOVERY], [test x"$enable_module_recovery" = x"ye
AM_CONDITIONAL([ENABLE_MODULE_EXTRAKEYS], [test x"$enable_module_extrakeys" = x"yes"])
AM_CONDITIONAL([ENABLE_MODULE_SCHNORRSIG], [test x"$enable_module_schnorrsig" = x"yes"])
AM_CONDITIONAL([USE_EXTERNAL_ASM], [test x"$enable_external_asm" = x"yes"])
AM_CONDITIONAL([USE_ASM_ARM], [test x"$set_asm" = x"arm"])
AM_CONDITIONAL([USE_ASM_ARM], [test x"$set_asm" = x"arm32"])
AM_CONDITIONAL([BUILD_WINDOWS], [test "$build_windows" = "yes"])
AC_SUBST(LIB_VERSION_CURRENT, _LIB_VERSION_CURRENT)
AC_SUBST(LIB_VERSION_REVISION, _LIB_VERSION_REVISION)

View File

@@ -16,8 +16,10 @@ This process also assumes that there will be no minor releases for old major rel
1. Open a PR to the master branch with a commit (using message `"release: prepare for $MAJOR.$MINOR.$PATCH"`, for example) that
* finalizes the release notes in [CHANGELOG.md](../CHANGELOG.md) (make sure to include an entry for `### ABI Compatibility`),
* updates `_PKG_VERSION_*` and `_LIB_VERSION_*` and sets `_PKG_VERSION_IS_RELEASE` to `true` in `configure.ac`, and
* updates `project(libsecp256k1 VERSION ...)` and `${PROJECT_NAME}_LIB_VERSION_*` in `CMakeLists.txt`.
* sets `_PKG_VERSION_IS_RELEASE` to `true` in `configure.ac`, and
* if this is not a patch release
* updates `_PKG_VERSION_*` and `_LIB_VERSION_*` in `configure.ac` and
* updates `project(libsecp256k1 VERSION ...)` and `${PROJECT_NAME}_LIB_VERSION_*` in `CMakeLists.txt`.
2. After the PR is merged, tag the commit and push it:
```
RELEASE_COMMIT=<merge commit of step 1>

View File

@@ -2,33 +2,26 @@ add_library(example INTERFACE)
target_include_directories(example INTERFACE
${PROJECT_SOURCE_DIR}/include
)
target_compile_options(example INTERFACE
$<$<C_COMPILER_ID:MSVC>:/wd4005>
)
target_link_libraries(example INTERFACE
secp256k1
$<$<PLATFORM_ID:Windows>:bcrypt>
)
if(SECP256K1_BUILD_SHARED)
target_link_libraries(example INTERFACE secp256k1)
elseif(SECP256K1_BUILD_STATIC)
target_link_libraries(example INTERFACE secp256k1_static)
if(MSVC)
target_link_options(example INTERFACE /IGNORE:4217)
endif()
if(NOT BUILD_SHARED_LIBS AND MSVC)
target_link_options(example INTERFACE /IGNORE:4217)
endif()
add_executable(ecdsa_example ecdsa.c)
target_link_libraries(ecdsa_example example)
add_test(ecdsa_example ecdsa_example)
add_test(NAME ecdsa_example COMMAND ecdsa_example)
if(SECP256K1_ENABLE_MODULE_ECDH)
add_executable(ecdh_example ecdh.c)
target_link_libraries(ecdh_example example)
add_test(ecdh_example ecdh_example)
add_test(NAME ecdh_example COMMAND ecdh_example)
endif()
if(SECP256K1_ENABLE_MODULE_SCHNORRSIG)
add_executable(schnorr_example schnorr.c)
target_link_libraries(schnorr_example example)
add_test(schnorr_example schnorr_example)
add_test(NAME schnorr_example COMMAND schnorr_example)
endif()

View File

@@ -17,7 +17,13 @@
*/
#if defined(_WIN32)
/*
* The defined WIN32_NO_STATUS macro disables return code definitions in
* windows.h, which avoids "macro redefinition" MSVC warnings in ntstatus.h.
*/
#define WIN32_NO_STATUS
#include <windows.h>
#undef WIN32_NO_STATUS
#include <ntstatus.h>
#include <bcrypt.h>
#elif defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)
@@ -77,7 +83,7 @@ static void print_hex(unsigned char* data, size_t size) {
#include <Windows.h>
#endif
/* Cleanses memory to prevent leaking sensitive info. Won't be optimized out. */
static SECP256K1_INLINE void secure_erase(void *ptr, size_t len) {
static void secure_erase(void *ptr, size_t len) {
#if defined(_MSC_VER)
/* SecureZeroMemory is guaranteed not to be optimized out by MSVC. */
SecureZeroMemory(ptr, len);

View File

@@ -122,18 +122,6 @@ typedef int (*secp256k1_nonce_function)(
# endif
# endif
# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
# if SECP256K1_GNUC_PREREQ(2,7)
# define SECP256K1_INLINE __inline__
# elif (defined(_MSC_VER))
# define SECP256K1_INLINE __inline
# else
# define SECP256K1_INLINE
# endif
# else
# define SECP256K1_INLINE inline
# endif
/* When this header is used at build-time the SECP256K1_BUILD define needs to be set
* to correctly setup export attributes and nullness checks. This is normally done
* by secp256k1.c but to guard against this header being included before secp256k1.c

View File

@@ -141,12 +141,20 @@ SECP256K1_API int secp256k1_schnorrsig_sign(
* variable length messages and accepts a pointer to an extraparams object that
* allows customizing signing by passing additional arguments.
*
* Creates the same signatures as schnorrsig_sign if msglen is 32 and the
* extraparams.ndata is the same as aux_rand32.
* Equivalent to secp256k1_schnorrsig_sign32(..., aux_rand32) if msglen is 32
* and extraparams is initialized as follows:
* ```
* secp256k1_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT;
* extraparams.ndata = (unsigned char*)aux_rand32;
* ```
*
* Returns 1 on success, 0 on failure.
* Args: ctx: pointer to a context object (not secp256k1_context_static).
* Out: sig64: pointer to a 64-byte array to store the serialized signature.
* In: msg: the message being signed. Can only be NULL if msglen is 0.
* msglen: length of the message
* extraparams: pointer to a extraparams object (can be NULL)
* msglen: length of the message.
* keypair: pointer to an initialized keypair.
* extraparams: pointer to an extraparams object (can be NULL).
*/
SECP256K1_API int secp256k1_schnorrsig_sign_custom(
const secp256k1_context *ctx,

View File

@@ -1,151 +1,162 @@
# Must be included before CMAKE_INSTALL_INCLUDEDIR is used.
include(GNUInstallDirs)
set(${PROJECT_NAME}_installables "")
if(SECP256K1_ASM STREQUAL "arm")
add_library(common OBJECT
asm/field_10x26_arm.s
)
set(common_obj "$<TARGET_OBJECTS:common>")
else()
set(common_obj "")
endif()
add_library(precomputed OBJECT
add_library(secp256k1_precomputed OBJECT EXCLUDE_FROM_ALL
precomputed_ecmult.c
precomputed_ecmult_gen.c
)
set(internal_obj "$<TARGET_OBJECTS:precomputed>" "${common_obj}")
add_library(secp256k1 SHARED EXCLUDE_FROM_ALL
secp256k1.c
${internal_obj}
)
target_include_directories(secp256k1 INTERFACE
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
target_compile_definitions(secp256k1 PRIVATE
$<$<PLATFORM_ID:Windows>:DLL_EXPORT>
)
set_target_properties(secp256k1 PROPERTIES
VERSION "${${PROJECT_NAME}_LIB_VERSION_CURRENT}.${${PROJECT_NAME}_LIB_VERSION_AGE}.${${PROJECT_NAME}_LIB_VERSION_REVISION}"
SOVERSION "${${PROJECT_NAME}_LIB_VERSION_CURRENT}"
)
if(SECP256K1_BUILD_SHARED)
get_target_property(use_pic secp256k1 POSITION_INDEPENDENT_CODE)
set_target_properties(precomputed PROPERTIES POSITION_INDEPENDENT_CODE ${use_pic})
set_target_properties(secp256k1 PROPERTIES EXCLUDE_FROM_ALL FALSE)
list(APPEND ${PROJECT_NAME}_installables secp256k1)
endif()
# Add objects explicitly rather than linking to the object libs to keep them
# from being exported.
add_library(secp256k1 secp256k1.c $<TARGET_OBJECTS:secp256k1_precomputed>)
add_library(secp256k1_static STATIC EXCLUDE_FROM_ALL
secp256k1.c
${internal_obj}
)
target_include_directories(secp256k1_static INTERFACE
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
if(NOT MSVC)
set_target_properties(secp256k1_static PROPERTIES
OUTPUT_NAME secp256k1
add_library(secp256k1_asm INTERFACE)
if(SECP256K1_ASM STREQUAL "arm32")
add_library(secp256k1_asm_arm OBJECT EXCLUDE_FROM_ALL)
target_sources(secp256k1_asm_arm PUBLIC
asm/field_10x26_arm.s
)
endif()
if(SECP256K1_BUILD_STATIC)
set_target_properties(secp256k1_static PROPERTIES EXCLUDE_FROM_ALL FALSE)
list(APPEND ${PROJECT_NAME}_installables secp256k1_static)
target_sources(secp256k1 PRIVATE $<TARGET_OBJECTS:secp256k1_asm_arm>)
target_link_libraries(secp256k1_asm INTERFACE secp256k1_asm_arm)
endif()
add_library(binary_interface INTERFACE)
target_compile_definitions(binary_interface INTERFACE
$<$<C_COMPILER_ID:MSVC>:_CRT_SECURE_NO_WARNINGS>
# Define our export symbol only for Win32 and only for shared libs.
# This matches libtool's usage of DLL_EXPORT
if(WIN32)
set_target_properties(secp256k1 PROPERTIES DEFINE_SYMBOL "DLL_EXPORT")
endif()
# Object libs don't know if they're being built for a shared or static lib.
# Grab the PIC property from secp256k1 which knows.
get_target_property(use_pic secp256k1 POSITION_INDEPENDENT_CODE)
set_target_properties(secp256k1_precomputed PROPERTIES POSITION_INDEPENDENT_CODE ${use_pic})
target_include_directories(secp256k1 INTERFACE
# Add the include path for parent projects so that they don't have to manually add it.
$<BUILD_INTERFACE:$<$<NOT:$<BOOL:${PROJECT_IS_TOP_LEVEL}>>:${PROJECT_SOURCE_DIR}/include>>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
add_library(link_library INTERFACE)
if(SECP256K1_BUILD_SHARED)
target_link_libraries(link_library INTERFACE secp256k1)
elseif(SECP256K1_BUILD_STATIC)
target_link_libraries(link_library INTERFACE secp256k1_static)
# This emulates Libtool to make sure Libtool and CMake agree on the ABI version,
# see below "Calculate the version variables" in build-aux/ltmain.sh.
math(EXPR ${PROJECT_NAME}_soversion "${${PROJECT_NAME}_LIB_VERSION_CURRENT} - ${${PROJECT_NAME}_LIB_VERSION_AGE}")
set_target_properties(secp256k1 PROPERTIES
SOVERSION ${${PROJECT_NAME}_soversion}
)
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set_target_properties(secp256k1 PROPERTIES
VERSION ${${PROJECT_NAME}_soversion}.${${PROJECT_NAME}_LIB_VERSION_AGE}.${${PROJECT_NAME}_LIB_VERSION_REVISION}
)
elseif(APPLE)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.17)
math(EXPR ${PROJECT_NAME}_compatibility_version "${${PROJECT_NAME}_LIB_VERSION_CURRENT} + 1")
set_target_properties(secp256k1 PROPERTIES
MACHO_COMPATIBILITY_VERSION ${${PROJECT_NAME}_compatibility_version}
MACHO_CURRENT_VERSION ${${PROJECT_NAME}_compatibility_version}.${${PROJECT_NAME}_LIB_VERSION_REVISION}
)
unset(${PROJECT_NAME}_compatibility_version)
elseif(BUILD_SHARED_LIBS)
message(WARNING
"The 'compatibility version' and 'current version' values of the DYLIB "
"will diverge from the values set by the GNU Libtool. To ensure "
"compatibility, it is recommended to upgrade CMake to at least version 3.17."
)
endif()
elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
set(${PROJECT_NAME}_windows "secp256k1")
if(MSVC)
set(${PROJECT_NAME}_windows "${PROJECT_NAME}")
endif()
set_target_properties(secp256k1 PROPERTIES
ARCHIVE_OUTPUT_NAME "${${PROJECT_NAME}_windows}"
RUNTIME_OUTPUT_NAME "${${PROJECT_NAME}_windows}-${${PROJECT_NAME}_soversion}"
)
unset(${PROJECT_NAME}_windows)
endif()
unset(${PROJECT_NAME}_soversion)
if(SECP256K1_BUILD_BENCHMARK)
add_executable(bench bench.c)
target_link_libraries(bench binary_interface link_library)
add_executable(bench_internal bench_internal.c ${internal_obj})
target_link_libraries(bench_internal binary_interface)
add_executable(bench_ecmult bench_ecmult.c ${internal_obj})
target_link_libraries(bench_ecmult binary_interface)
target_link_libraries(bench secp256k1)
add_executable(bench_internal bench_internal.c)
target_link_libraries(bench_internal secp256k1_precomputed secp256k1_asm)
add_executable(bench_ecmult bench_ecmult.c)
target_link_libraries(bench_ecmult secp256k1_precomputed secp256k1_asm)
endif()
if(SECP256K1_BUILD_TESTS)
add_executable(noverify_tests tests.c ${internal_obj})
target_link_libraries(noverify_tests binary_interface)
add_test(noverify_tests noverify_tests)
add_executable(noverify_tests tests.c)
target_link_libraries(noverify_tests secp256k1_precomputed secp256k1_asm)
add_test(NAME noverify_tests COMMAND noverify_tests)
if(NOT CMAKE_BUILD_TYPE STREQUAL "Coverage")
add_executable(tests tests.c ${internal_obj})
add_executable(tests tests.c)
target_compile_definitions(tests PRIVATE VERIFY)
target_link_libraries(tests binary_interface)
add_test(tests tests)
target_link_libraries(tests secp256k1_precomputed secp256k1_asm)
add_test(NAME tests COMMAND tests)
endif()
endif()
if(SECP256K1_BUILD_EXHAUSTIVE_TESTS)
# Note: do not include $<TARGET_OBJECTS:precomputed> in exhaustive_tests (it uses runtime-generated tables).
add_executable(exhaustive_tests tests_exhaustive.c ${common_obj})
# Note: do not include secp256k1_precomputed in exhaustive_tests (it uses runtime-generated tables).
add_executable(exhaustive_tests tests_exhaustive.c)
target_link_libraries(exhaustive_tests secp256k1_asm)
target_compile_definitions(exhaustive_tests PRIVATE $<$<NOT:$<CONFIG:Coverage>>:VERIFY>)
target_link_libraries(exhaustive_tests binary_interface)
add_test(exhaustive_tests exhaustive_tests)
add_test(NAME exhaustive_tests COMMAND exhaustive_tests)
endif()
if(SECP256K1_BUILD_CTIME_TESTS)
add_executable(ctime_tests ctime_tests.c)
target_link_libraries(ctime_tests binary_interface link_library)
target_link_libraries(ctime_tests secp256k1)
endif()
install(TARGETS ${${PROJECT_NAME}_installables}
EXPORT ${PROJECT_NAME}-targets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
set(${PROJECT_NAME}_headers
"${PROJECT_SOURCE_DIR}/include/secp256k1.h"
"${PROJECT_SOURCE_DIR}/include/secp256k1_preallocated.h"
)
if(SECP256K1_ENABLE_MODULE_ECDH)
list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_ecdh.h")
endif()
if(SECP256K1_ENABLE_MODULE_RECOVERY)
list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_recovery.h")
endif()
if(SECP256K1_ENABLE_MODULE_EXTRAKEYS)
list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_extrakeys.h")
endif()
if(SECP256K1_ENABLE_MODULE_SCHNORRSIG)
list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_schnorrsig.h")
endif()
install(FILES ${${PROJECT_NAME}_headers}
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
if(SECP256K1_INSTALL)
install(TARGETS secp256k1
EXPORT ${PROJECT_NAME}-targets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
set(${PROJECT_NAME}_headers
"${PROJECT_SOURCE_DIR}/include/secp256k1.h"
"${PROJECT_SOURCE_DIR}/include/secp256k1_preallocated.h"
)
if(SECP256K1_ENABLE_MODULE_ECDH)
list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_ecdh.h")
endif()
if(SECP256K1_ENABLE_MODULE_RECOVERY)
list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_recovery.h")
endif()
if(SECP256K1_ENABLE_MODULE_EXTRAKEYS)
list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_extrakeys.h")
endif()
if(SECP256K1_ENABLE_MODULE_SCHNORRSIG)
list(APPEND ${PROJECT_NAME}_headers "${PROJECT_SOURCE_DIR}/include/secp256k1_schnorrsig.h")
endif()
install(FILES ${${PROJECT_NAME}_headers}
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
install(EXPORT ${PROJECT_NAME}-targets
FILE ${PROJECT_NAME}-targets.cmake
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
)
install(EXPORT ${PROJECT_NAME}-targets
FILE ${PROJECT_NAME}-targets.cmake
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
)
include(CMakePackageConfigHelpers)
configure_package_config_file(
${PROJECT_SOURCE_DIR}/cmake/config.cmake.in
${PROJECT_NAME}-config.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
NO_SET_AND_CHECK_MACRO
)
write_basic_package_version_file(${PROJECT_NAME}-config-version.cmake
COMPATIBILITY SameMajorVersion
)
install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
include(CMakePackageConfigHelpers)
configure_package_config_file(
${PROJECT_SOURCE_DIR}/cmake/config.cmake.in
${PROJECT_NAME}-config.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
NO_SET_AND_CHECK_MACRO
)
write_basic_package_version_file(${PROJECT_NAME}-config-version.cmake
COMPATIBILITY SameMinorVersion
)
install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config.cmake
${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}-config-version.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}
)
endif()

View File

@@ -64,11 +64,11 @@ typedef struct {
size_t siglen;
unsigned char pubkey[33];
size_t pubkeylen;
} bench_verify_data;
} bench_data;
static void bench_verify(void* arg, int iters) {
int i;
bench_verify_data* data = (bench_verify_data*)arg;
bench_data* data = (bench_data*)arg;
for (i = 0; i < iters; i++) {
secp256k1_pubkey pubkey;
@@ -85,15 +85,9 @@ static void bench_verify(void* arg, int iters) {
}
}
typedef struct {
secp256k1_context* ctx;
unsigned char msg[32];
unsigned char key[32];
} bench_sign_data;
static void bench_sign_setup(void* arg) {
int i;
bench_sign_data *data = (bench_sign_data*)arg;
bench_data *data = (bench_data*)arg;
for (i = 0; i < 32; i++) {
data->msg[i] = i + 1;
@@ -105,7 +99,7 @@ static void bench_sign_setup(void* arg) {
static void bench_sign_run(void* arg, int iters) {
int i;
bench_sign_data *data = (bench_sign_data*)arg;
bench_data *data = (bench_data*)arg;
unsigned char sig[74];
for (i = 0; i < iters; i++) {
@@ -137,7 +131,7 @@ int main(int argc, char** argv) {
int i;
secp256k1_pubkey pubkey;
secp256k1_ecdsa_signature sig;
bench_verify_data data;
bench_data data;
int d = argc == 1;
int default_iters = 20000;

View File

@@ -15,7 +15,7 @@
#if (defined(_MSC_VER) && _MSC_VER >= 1900)
# include <time.h>
#else
# include "sys/time.h"
# include <sys/time.h>
#endif
static int64_t gettime_i64(void) {

View File

@@ -113,7 +113,7 @@ static void bench_ecmult_const(void* arg, int iters) {
int i;
for (i = 0; i < iters; ++i) {
secp256k1_ecmult_const(&data->output[i], &data->pubkeys[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS], 256);
secp256k1_ecmult_const(&data->output[i], &data->pubkeys[(data->offset1+i) % POINTS], &data->scalars[(data->offset2+i) % POINTS]);
}
}

View File

@@ -65,10 +65,10 @@ static void bench_setup(void* arg) {
secp256k1_scalar_set_b32(&data->scalar[0], init[0], NULL);
secp256k1_scalar_set_b32(&data->scalar[1], init[1], NULL);
secp256k1_fe_set_b32(&data->fe[0], init[0]);
secp256k1_fe_set_b32(&data->fe[1], init[1]);
secp256k1_fe_set_b32(&data->fe[2], init[2]);
secp256k1_fe_set_b32(&data->fe[3], init[3]);
secp256k1_fe_set_b32_limit(&data->fe[0], init[0]);
secp256k1_fe_set_b32_limit(&data->fe[1], init[1]);
secp256k1_fe_set_b32_limit(&data->fe[2], init[2]);
secp256k1_fe_set_b32_limit(&data->fe[3], init[3]);
CHECK(secp256k1_ge_set_xo_var(&data->ge[0], &data->fe[0], 0));
CHECK(secp256k1_ge_set_xo_var(&data->ge[1], &data->fe[1], 1));
secp256k1_gej_set_ge(&data->gej[0], &data->ge[0]);

View File

@@ -239,7 +239,8 @@ static int secp256k1_ecdsa_sig_verify(const secp256k1_scalar *sigr, const secp25
}
#else
secp256k1_scalar_get_b32(c, sigr);
secp256k1_fe_set_b32(&xr, c);
/* we can ignore the fe_set_b32_limit return value, because we know the input is in range */
(void)secp256k1_fe_set_b32_limit(&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),

View File

@@ -17,10 +17,10 @@
static int secp256k1_eckey_pubkey_parse(secp256k1_ge *elem, const unsigned char *pub, size_t size) {
if (size == 33 && (pub[0] == SECP256K1_TAG_PUBKEY_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_ODD)) {
secp256k1_fe x;
return secp256k1_fe_set_b32(&x, pub+1) && secp256k1_ge_set_xo_var(elem, &x, pub[0] == SECP256K1_TAG_PUBKEY_ODD);
return secp256k1_fe_set_b32_limit(&x, pub+1) && secp256k1_ge_set_xo_var(elem, &x, pub[0] == SECP256K1_TAG_PUBKEY_ODD);
} else if (size == 65 && (pub[0] == SECP256K1_TAG_PUBKEY_UNCOMPRESSED || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_EVEN || pub[0] == SECP256K1_TAG_PUBKEY_HYBRID_ODD)) {
secp256k1_fe x, y;
if (!secp256k1_fe_set_b32(&x, pub+1) || !secp256k1_fe_set_b32(&y, pub+33)) {
if (!secp256k1_fe_set_b32_limit(&x, pub+1) || !secp256k1_fe_set_b32_limit(&y, pub+33)) {
return 0;
}
secp256k1_ge_set_xy(elem, &x, &y);

View File

@@ -11,12 +11,9 @@
#include "group.h"
/**
* Multiply: R = q*A (in constant-time)
* Here `bits` should be set to the maximum bitlength of the _absolute value_ of `q`, plus
* one because we internally sometimes add 2 to the number during the WNAF conversion.
* A must not be infinity.
* Multiply: R = q*A (in constant-time for q)
*/
static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q, int bits);
static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *q);
/**
* Same as secp256k1_ecmult_const, but takes in an x coordinate of the base point
@@ -35,7 +32,6 @@ static int secp256k1_ecmult_const_xonly(
const secp256k1_fe *n,
const secp256k1_fe *d,
const secp256k1_scalar *q,
int bits,
int known_on_curve
);

View File

@@ -29,7 +29,7 @@ static void secp256k1_ecmult_odd_multiples_table_globalz_windowa(secp256k1_ge *p
#define ECMULT_CONST_TABLE_GET_GE(r,pre,n,w) do { \
int m = 0; \
/* Extract the sign-bit for a constant time absolute-value. */ \
int mask = (n) >> (sizeof(n) * CHAR_BIT - 1); \
int volatile mask = (n) >> (sizeof(n) * CHAR_BIT - 1); \
int abs_n = ((n) + mask) ^ mask; \
int idx_n = abs_n >> 1; \
secp256k1_fe neg_y; \
@@ -130,7 +130,7 @@ static int secp256k1_wnaf_const(int *wnaf, const secp256k1_scalar *scalar, int w
return skew;
}
static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *scalar, int size) {
static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, const secp256k1_scalar *scalar) {
secp256k1_ge pre_a[ECMULT_TABLE_SIZE(WINDOW_A)];
secp256k1_ge tmpa;
secp256k1_fe Z;
@@ -144,20 +144,17 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
int i;
/* build wnaf representation for q. */
int rsize = size;
if (size > 128) {
rsize = 128;
/* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */
secp256k1_scalar_split_lambda(&q_1, &q_lam, scalar);
skew_1 = secp256k1_wnaf_const(wnaf_1, &q_1, WINDOW_A - 1, 128);
skew_lam = secp256k1_wnaf_const(wnaf_lam, &q_lam, WINDOW_A - 1, 128);
} else
{
skew_1 = secp256k1_wnaf_const(wnaf_1, scalar, WINDOW_A - 1, size);
skew_lam = 0;
if (secp256k1_ge_is_infinity(a)) {
secp256k1_gej_set_infinity(r);
return;
}
/* build wnaf representation for q. */
/* split q into q_1 and q_lam (where q = q_1 + q_lam*lambda, and q_1 and q_lam are ~128 bit) */
secp256k1_scalar_split_lambda(&q_1, &q_lam, scalar);
skew_1 = secp256k1_wnaf_const(wnaf_1, &q_1, WINDOW_A - 1, 128);
skew_lam = secp256k1_wnaf_const(wnaf_lam, &q_lam, WINDOW_A - 1, 128);
/* Calculate odd multiples of a.
* All multiples are brought to the same Z 'denominator', which is stored
* in Z. Due to secp256k1' isomorphism we can do all operations pretending
@@ -170,28 +167,23 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {
secp256k1_fe_normalize_weak(&pre_a[i].y);
}
if (size > 128) {
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {
secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]);
}
for (i = 0; i < ECMULT_TABLE_SIZE(WINDOW_A); i++) {
secp256k1_ge_mul_lambda(&pre_a_lam[i], &pre_a[i]);
}
/* first loop iteration (separated out so we can directly set r, rather
* than having it start at infinity, get doubled several times, then have
* its new value added to it) */
i = wnaf_1[WNAF_SIZE_BITS(rsize, WINDOW_A - 1)];
i = wnaf_1[WNAF_SIZE_BITS(128, WINDOW_A - 1)];
VERIFY_CHECK(i != 0);
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, i, WINDOW_A);
secp256k1_gej_set_ge(r, &tmpa);
if (size > 128) {
i = wnaf_lam[WNAF_SIZE_BITS(rsize, WINDOW_A - 1)];
VERIFY_CHECK(i != 0);
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, i, WINDOW_A);
secp256k1_gej_add_ge(r, r, &tmpa);
}
i = wnaf_lam[WNAF_SIZE_BITS(128, WINDOW_A - 1)];
VERIFY_CHECK(i != 0);
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, i, WINDOW_A);
secp256k1_gej_add_ge(r, r, &tmpa);
/* remaining loop iterations */
for (i = WNAF_SIZE_BITS(rsize, WINDOW_A - 1) - 1; i >= 0; i--) {
for (i = WNAF_SIZE_BITS(128, WINDOW_A - 1) - 1; i >= 0; i--) {
int n;
int j;
for (j = 0; j < WINDOW_A - 1; ++j) {
@@ -202,12 +194,10 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a, n, WINDOW_A);
VERIFY_CHECK(n != 0);
secp256k1_gej_add_ge(r, r, &tmpa);
if (size > 128) {
n = wnaf_lam[i];
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A);
VERIFY_CHECK(n != 0);
secp256k1_gej_add_ge(r, r, &tmpa);
}
n = wnaf_lam[i];
ECMULT_CONST_TABLE_GET_GE(&tmpa, pre_a_lam, n, WINDOW_A);
VERIFY_CHECK(n != 0);
secp256k1_gej_add_ge(r, r, &tmpa);
}
{
@@ -218,17 +208,15 @@ static void secp256k1_ecmult_const(secp256k1_gej *r, const secp256k1_ge *a, cons
secp256k1_gej_add_ge(&tmpj, r, &tmpa);
secp256k1_gej_cmov(r, &tmpj, skew_1);
if (size > 128) {
secp256k1_ge_neg(&tmpa, &pre_a_lam[0]);
secp256k1_gej_add_ge(&tmpj, r, &tmpa);
secp256k1_gej_cmov(r, &tmpj, skew_lam);
}
secp256k1_ge_neg(&tmpa, &pre_a_lam[0]);
secp256k1_gej_add_ge(&tmpj, r, &tmpa);
secp256k1_gej_cmov(r, &tmpj, skew_lam);
}
secp256k1_fe_mul(&r->z, &r->z, &Z);
}
static int secp256k1_ecmult_const_xonly(secp256k1_fe* r, const secp256k1_fe *n, const secp256k1_fe *d, const secp256k1_scalar *q, int bits, int known_on_curve) {
static int secp256k1_ecmult_const_xonly(secp256k1_fe* r, const secp256k1_fe *n, const secp256k1_fe *d, const secp256k1_scalar *q, int known_on_curve) {
/* This algorithm is a generalization of Peter Dettman's technique for
* avoiding the square root in a random-basepoint x-only multiplication
@@ -346,7 +334,7 @@ static int secp256k1_ecmult_const_xonly(secp256k1_fe* r, const secp256k1_fe *n,
#ifdef VERIFY
VERIFY_CHECK(!secp256k1_scalar_is_zero(q));
#endif
secp256k1_ecmult_const(&rj, &p, q, bits);
secp256k1_ecmult_const(&rj, &p, q);
#ifdef VERIFY
VERIFY_CHECK(!secp256k1_gej_is_infinity(&rj));
#endif

View File

@@ -31,7 +31,7 @@ static void secp256k1_ecmult_gen_compute_table(secp256k1_ge_storage* table, cons
secp256k1_fe nums_x;
secp256k1_ge nums_ge;
int r;
r = secp256k1_fe_set_b32(&nums_x, nums_b32);
r = secp256k1_fe_set_b32_limit(&nums_x, nums_b32);
(void)r;
VERIFY_CHECK(r);
r = secp256k1_ge_set_xo_var(&nums_ge, &nums_x, 0);

View File

@@ -108,7 +108,7 @@ static void secp256k1_ecmult_gen_blind(secp256k1_ecmult_gen_context *ctx, const
memset(keydata, 0, sizeof(keydata));
/* Accept unobservably small non-uniformity. */
secp256k1_rfc6979_hmac_sha256_generate(&rng, nonce32, 32);
overflow = !secp256k1_fe_set_b32(&s, nonce32);
overflow = !secp256k1_fe_set_b32_limit(&s, nonce32);
overflow |= secp256k1_fe_is_zero(&s);
secp256k1_fe_cmov(&s, &secp256k1_fe_one, overflow);
/* Randomize the projection to defend against multiplier sidechannels.

View File

@@ -279,9 +279,6 @@ static void secp256k1_ecmult_strauss_wnaf(const struct secp256k1_strauss_state *
*/
tmp = a[np];
if (no) {
#ifdef VERIFY
secp256k1_fe_normalize_var(&Z);
#endif
secp256k1_gej_rescale(&tmp, &Z);
}
secp256k1_ecmult_odd_multiples_table(ECMULT_TABLE_SIZE(WINDOW_A), state->pre_a + no * ECMULT_TABLE_SIZE(WINDOW_A), state->aux + no * ECMULT_TABLE_SIZE(WINDOW_A), &Z, &tmp);
@@ -683,7 +680,7 @@ static int secp256k1_ecmult_pippenger_batch(const secp256k1_callback* error_call
}
state_space->ps = (struct secp256k1_pippenger_point_state *) secp256k1_scratch_alloc(error_callback, scratch, entries * sizeof(*state_space->ps));
state_space->wnaf_na = (int *) secp256k1_scratch_alloc(error_callback, scratch, entries*(WNAF_SIZE(bucket_window+1)) * sizeof(int));
buckets = (secp256k1_gej *) secp256k1_scratch_alloc(error_callback, scratch, (1<<bucket_window) * sizeof(*buckets));
buckets = (secp256k1_gej *) secp256k1_scratch_alloc(error_callback, scratch, ((size_t)1 << bucket_window) * sizeof(*buckets));
if (state_space->ps == NULL || state_space->wnaf_na == NULL || buckets == NULL) {
secp256k1_scratch_apply_checkpoint(error_callback, scratch, scratch_checkpoint);
return 0;

View File

@@ -7,19 +7,36 @@
#ifndef SECP256K1_FIELD_H
#define SECP256K1_FIELD_H
/** Field element module.
*
* Field elements can be represented in several ways, but code accessing
* it (and implementations) need to take certain properties into account:
* - Each field element can be normalized or not.
* - Each field element has a magnitude, which represents how far away
* its representation is away from normalization. Normalized elements
* always have a magnitude of 0 or 1, but a magnitude of 1 doesn't
* imply normality.
*/
#include "util.h"
/* This file defines the generic interface for working with secp256k1_fe
* objects, which represent field elements (integers modulo 2^256 - 2^32 - 977).
*
* The actual definition of the secp256k1_fe type depends on the chosen field
* implementation; see the field_5x52.h and field_10x26.h files for details.
*
* All secp256k1_fe objects have implicit properties that determine what
* operations are permitted on it. These are purely a function of what
* secp256k1_fe_ operations are applied on it, generally (implicitly) fixed at
* compile time, and do not depend on the chosen field implementation. Despite
* that, what these properties actually entail for the field representation
* values depends on the chosen field implementation. These properties are:
* - magnitude: an integer in [0,32]
* - normalized: 0 or 1; normalized=1 implies magnitude <= 1.
*
* In VERIFY mode, they are materialized explicitly as fields in the struct,
* allowing run-time verification of these properties. In that case, the field
* implementation also provides a secp256k1_fe_verify routine to verify that
* these fields match the run-time value and perform internal consistency
* checks. */
#ifdef VERIFY
# define SECP256K1_FE_VERIFY_FIELDS \
int magnitude; \
int normalized;
#else
# define SECP256K1_FE_VERIFY_FIELDS
#endif
#if defined(SECP256K1_WIDEMUL_INT128)
#include "field_5x52.h"
#elif defined(SECP256K1_WIDEMUL_INT64)
@@ -28,117 +45,295 @@
#error "Please select wide multiplication implementation"
#endif
#ifdef VERIFY
/* Magnitude and normalized value for constants. */
#define SECP256K1_FE_VERIFY_CONST(d7, d6, d5, d4, d3, d2, d1, d0) \
/* Magnitude is 0 for constant 0; 1 otherwise. */ \
, (((d7) | (d6) | (d5) | (d4) | (d3) | (d2) | (d1) | (d0)) != 0) \
/* Normalized is 1 unless sum(d_i<<(32*i) for i=0..7) exceeds field modulus. */ \
, (!(((d7) & (d6) & (d5) & (d4) & (d3) & (d2)) == 0xfffffffful && ((d1) == 0xfffffffful || ((d1) == 0xfffffffe && (d0 >= 0xfffffc2f)))))
#else
#define SECP256K1_FE_VERIFY_CONST(d7, d6, d5, d4, d3, d2, d1, d0)
#endif
/** This expands to an initializer for a secp256k1_fe valued sum((i*32) * d_i, i=0..7) mod p.
*
* It has magnitude 1, unless d_i are all 0, in which case the magnitude is 0.
* It is normalized, unless sum(2^(i*32) * d_i, i=0..7) >= p.
*
* SECP256K1_FE_CONST_INNER is provided by the implementation.
*/
#define SECP256K1_FE_CONST(d7, d6, d5, d4, d3, d2, d1, d0) {SECP256K1_FE_CONST_INNER((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)) SECP256K1_FE_VERIFY_CONST((d7), (d6), (d5), (d4), (d3), (d2), (d1), (d0)) }
static const secp256k1_fe secp256k1_fe_one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1);
static const secp256k1_fe secp256k1_const_beta = SECP256K1_FE_CONST(
0x7ae96a2bul, 0x657c0710ul, 0x6e64479eul, 0xac3434e9ul,
0x9cf04975ul, 0x12f58995ul, 0xc1396c28ul, 0x719501eeul
);
/** Normalize a field element. This brings the field element to a canonical representation, reduces
* its magnitude to 1, and reduces it modulo field size `p`.
#ifndef VERIFY
/* In non-VERIFY mode, we #define the fe operations to be identical to their
* internal field implementation, to avoid the potential overhead of a
* function call (even though presumably inlinable). */
# define secp256k1_fe_normalize secp256k1_fe_impl_normalize
# define secp256k1_fe_normalize_weak secp256k1_fe_impl_normalize_weak
# define secp256k1_fe_normalize_var secp256k1_fe_impl_normalize_var
# define secp256k1_fe_normalizes_to_zero secp256k1_fe_impl_normalizes_to_zero
# define secp256k1_fe_normalizes_to_zero_var secp256k1_fe_impl_normalizes_to_zero_var
# define secp256k1_fe_set_int secp256k1_fe_impl_set_int
# define secp256k1_fe_clear secp256k1_fe_impl_clear
# define secp256k1_fe_is_zero secp256k1_fe_impl_is_zero
# define secp256k1_fe_is_odd secp256k1_fe_impl_is_odd
# define secp256k1_fe_cmp_var secp256k1_fe_impl_cmp_var
# define secp256k1_fe_set_b32_mod secp256k1_fe_impl_set_b32_mod
# define secp256k1_fe_set_b32_limit secp256k1_fe_impl_set_b32_limit
# define secp256k1_fe_get_b32 secp256k1_fe_impl_get_b32
# define secp256k1_fe_negate secp256k1_fe_impl_negate
# define secp256k1_fe_mul_int secp256k1_fe_impl_mul_int
# define secp256k1_fe_add secp256k1_fe_impl_add
# define secp256k1_fe_mul secp256k1_fe_impl_mul
# define secp256k1_fe_sqr secp256k1_fe_impl_sqr
# define secp256k1_fe_cmov secp256k1_fe_impl_cmov
# define secp256k1_fe_to_storage secp256k1_fe_impl_to_storage
# define secp256k1_fe_from_storage secp256k1_fe_impl_from_storage
# define secp256k1_fe_inv secp256k1_fe_impl_inv
# define secp256k1_fe_inv_var secp256k1_fe_impl_inv_var
# define secp256k1_fe_get_bounds secp256k1_fe_impl_get_bounds
# define secp256k1_fe_half secp256k1_fe_impl_half
# define secp256k1_fe_add_int secp256k1_fe_impl_add_int
# define secp256k1_fe_is_square_var secp256k1_fe_impl_is_square_var
#endif /* !defined(VERIFY) */
/** Normalize a field element.
*
* On input, r must be a valid field element.
* On output, r represents the same value but has normalized=1 and magnitude=1.
*/
static void secp256k1_fe_normalize(secp256k1_fe *r);
/** Weakly normalize a field element: reduce its magnitude to 1, but don't fully normalize. */
/** Give a field element magnitude 1.
*
* On input, r must be a valid field element.
* On output, r represents the same value but has magnitude=1. Normalized is unchanged.
*/
static void secp256k1_fe_normalize_weak(secp256k1_fe *r);
/** Normalize a field element, without constant-time guarantee. */
/** Normalize a field element, without constant-time guarantee.
*
* Identical in behavior to secp256k1_fe_normalize, but not constant time in r.
*/
static void secp256k1_fe_normalize_var(secp256k1_fe *r);
/** Verify whether a field element represents zero i.e. would normalize to a zero value. */
/** Determine whether r represents field element 0.
*
* On input, r must be a valid field element.
* Returns whether r = 0 (mod p).
*/
static int secp256k1_fe_normalizes_to_zero(const secp256k1_fe *r);
/** Verify whether a field element represents zero i.e. would normalize to a zero value,
* without constant-time guarantee. */
/** Determine whether r represents field element 0, without constant-time guarantee.
*
* Identical in behavior to secp256k1_normalizes_to_zero, but not constant time in r.
*/
static int secp256k1_fe_normalizes_to_zero_var(const secp256k1_fe *r);
/** Set a field element equal to a small (not greater than 0x7FFF), non-negative integer.
* Resulting field element is normalized; it has magnitude 0 if a == 0, and magnitude 1 otherwise.
/** Set a field element to an integer in range [0,0x7FFF].
*
* On input, r does not need to be initialized, a must be in [0,0x7FFF].
* On output, r represents value a, is normalized and has magnitude (a!=0).
*/
static void secp256k1_fe_set_int(secp256k1_fe *r, int a);
/** Sets a field element equal to zero, initializing all fields. */
/** Set a field element to 0.
*
* On input, a does not need to be initialized.
* On output, a represents 0, is normalized and has magnitude 0.
*/
static void secp256k1_fe_clear(secp256k1_fe *a);
/** Verify whether a field element is zero. Requires the input to be normalized. */
/** Determine whether a represents field element 0.
*
* On input, a must be a valid normalized field element.
* Returns whether a = 0 (mod p).
*
* This behaves identical to secp256k1_normalizes_to_zero{,_var}, but requires
* normalized input (and is much faster).
*/
static int secp256k1_fe_is_zero(const secp256k1_fe *a);
/** Check the "oddness" of a field element. Requires the input to be normalized. */
/** Determine whether a (mod p) is odd.
*
* On input, a must be a valid normalized field element.
* Returns (int(a) mod p) & 1.
*/
static int secp256k1_fe_is_odd(const secp256k1_fe *a);
/** Compare two field elements. Requires magnitude-1 inputs. */
/** Determine whether two field elements are equal.
*
* On input, a and b must be valid field elements with magnitudes not exceeding
* 1 and 31, respectively.
* Returns a = b (mod p).
*/
static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b);
/** Same as secp256k1_fe_equal, but may be variable time. */
/** Determine whether two field elements are equal, without constant-time guarantee.
*
* Identical in behavior to secp256k1_fe_equal, but not constant time in either a or b.
*/
static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b);
/** Compare two field elements. Requires both inputs to be normalized */
/** Compare the values represented by 2 field elements, without constant-time guarantee.
*
* On input, a and b must be valid normalized field elements.
* Returns 1 if a > b, -1 if a < b, and 0 if a = b (comparisons are done as integers
* in range 0..p-1).
*/
static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b);
/** Set a field element equal to 32-byte big endian value. If successful, the resulting field element is normalized. */
static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a);
/** Set a field element equal to a provided 32-byte big endian value, reducing it.
*
* On input, r does not need to be initalized. a must be a pointer to an initialized 32-byte array.
* On output, r = a (mod p). It will have magnitude 1, and not be normalized.
*/
static void secp256k1_fe_set_b32_mod(secp256k1_fe *r, const unsigned char *a);
/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
/** Set a field element equal to a provided 32-byte big endian value, checking for overflow.
*
* On input, r does not need to be initalized. a must be a pointer to an initialized 32-byte array.
* On output, r = a if (a < p), it will be normalized with magnitude 1, and 1 is returned.
* If a >= p, 0 is returned, and r will be made invalid (and must not be used without overwriting).
*/
static int secp256k1_fe_set_b32_limit(secp256k1_fe *r, const unsigned char *a);
/** Convert a field element to 32-byte big endian byte array.
* On input, a must be a valid normalized field element, and r a pointer to a 32-byte array.
* On output, r = a (mod p).
*/
static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a);
/** Set a field element equal to the additive inverse of another. Takes a maximum magnitude of the input
* as an argument. The magnitude of the output is one higher. */
/** Negate a field element.
*
* On input, r does not need to be initialized. a must be a valid field element with
* magnitude not exceeding m. m must be an integer in [0,31].
* Performs {r = -a}.
* On output, r will not be normalized, and will have magnitude m+1.
*/
static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m);
/** Adds a small integer (up to 0x7FFF) to r. The resulting magnitude increases by one. */
/** Add a small integer to a field element.
*
* Performs {r += a}. The magnitude of r increases by 1, and normalized is cleared.
* a must be in range [0,0xFFFF].
*/
static void secp256k1_fe_add_int(secp256k1_fe *r, int a);
/** Multiplies the passed field element with a small integer constant. Multiplies the magnitude by that
* small integer. */
/** Multiply a field element with a small integer.
*
* On input, r must be a valid field element. a must be an integer in [0,32].
* The magnitude of r times a must not exceed 32.
* Performs {r *= a}.
* On output, r's magnitude is multiplied by a, and r will not be normalized.
*/
static void secp256k1_fe_mul_int(secp256k1_fe *r, int a);
/** Adds a field element to another. The result has the sum of the inputs' magnitudes as magnitude. */
/** Increment a field element by another.
*
* On input, r and a must be valid field elements, not necessarily normalized.
* The sum of their magnitudes must not exceed 32.
* Performs {r += a}.
* On output, r will not be normalized, and will have magnitude incremented by a's.
*/
static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a);
/** Sets a field element to be the product of two others. Requires the inputs' magnitudes to be at most 8.
* The output magnitude is 1 (but not guaranteed to be normalized). */
/** Multiply two field elements.
*
* On input, a and b must be valid field elements; r does not need to be initialized.
* r and a may point to the same object, but neither can be equal to b. The magnitudes
* of a and b must not exceed 8.
* Performs {r = a * b}
* On output, r will have magnitude 1, but won't be normalized.
*/
static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b);
/** Sets a field element to be the square of another. Requires the input's magnitude to be at most 8.
* The output magnitude is 1 (but not guaranteed to be normalized). */
/** Square a field element.
*
* On input, a must be a valid field element; r does not need to be initialized. The magnitude
* of a must not exceed 8.
* Performs {r = a**2}
* On output, r will have magnitude 1, but won't be normalized.
*/
static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a);
/** If a has a square root, it is computed in r and 1 is returned. If a does not
* have a square root, the root of its negation is computed and 0 is returned.
* The input's magnitude can be at most 8. The output magnitude is 1 (but not
* guaranteed to be normalized). The result in r will always be a square
* itself. */
static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a);
/** Compute a square root of a field element.
*
* On input, a must be a valid field element with magnitude<=8; r need not be initialized.
* Performs {r = sqrt(a)} or {r = sqrt(-a)}, whichever exists. The resulting value
* represented by r will be a square itself. Variables r and a must not point to the same object.
* On output, r will have magnitude 1 but will not be normalized.
*/
static int secp256k1_fe_sqrt(secp256k1_fe * SECP256K1_RESTRICT r, const secp256k1_fe * SECP256K1_RESTRICT a);
/** Sets a field element to be the (modular) inverse of another. Requires the input's magnitude to be
* at most 8. The output magnitude is 1 (but not guaranteed to be normalized). */
/** Compute the modular inverse of a field element.
*
* On input, a must be a valid field element; r need not be initialized.
* Performs {r = a**(p-2)} (which maps 0 to 0, and every other element to its
* inverse).
* On output, r will have magnitude (a.magnitude != 0) and be normalized.
*/
static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *a);
/** Potentially faster version of secp256k1_fe_inv, without constant-time guarantee. */
/** Compute the modular inverse of a field element, without constant-time guarantee.
*
* Behaves identically to secp256k1_fe_inv, but is not constant-time in a.
*/
static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *a);
/** Convert a field element to the storage type. */
/** Convert a field element to secp256k1_fe_storage.
*
* On input, a must be a valid normalized field element.
* Performs {r = a}.
*/
static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a);
/** Convert a field element back from the storage type. */
/** Convert a field element back from secp256k1_fe_storage.
*
* On input, r need not be initialized.
* Performs {r = a}.
* On output, r will be normalized and will have magnitude 1.
*/
static void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a);
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/
static void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag);
/** If flag is true, set *r equal to *a; otherwise leave it. Constant-time. Both *r and *a must be initialized.*/
/** Conditionally move a field element in constant time.
*
* On input, both r and a must be valid field elements. Flag must be 0 or 1.
* Performs {r = flag ? a : r}.
* On output, r's magnitude and normalized will equal a's in case of flag=1, unchanged otherwise.
*/
static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag);
/** Halves the value of a field element modulo the field prime. Constant-time.
* For an input magnitude 'm', the output magnitude is set to 'floor(m/2) + 1'.
* The output is not guaranteed to be normalized, regardless of the input. */
/** Halve the value of a field element modulo the field prime in constant-time.
*
* On input, r must be a valid field element.
* On output, r will be normalized and have magnitude floor(m/2) + 1 where m is
* the magnitude of r on input.
*/
static void secp256k1_fe_half(secp256k1_fe *r);
/** Sets each limb of 'r' to its upper bound at magnitude 'm'. The output will also have its
* magnitude set to 'm' and is normalized if (and only if) 'm' is zero. */
/** Sets r to a field element with magnitude m, normalized if (and only if) m==0.
* The value is chosen so that it is likely to trigger edge cases related to
* internal overflows. */
static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m);
/** Determine whether a is a square (modulo p). */
/** Determine whether a is a square (modulo p).
*
* On input, a must be a valid field element.
*/
static int secp256k1_fe_is_square_var(const secp256k1_fe *a);
/** Check invariants on a field element (no-op unless VERIFY is enabled). */
static void secp256k1_fe_verify(const secp256k1_fe *a);
#endif /* SECP256K1_FIELD_H */

View File

@@ -9,15 +9,28 @@
#include <stdint.h>
/** This field implementation represents the value as 10 uint32_t limbs in base
* 2^26. */
typedef struct {
/* X = sum(i=0..9, n[i]*2^(i*26)) mod p
* where p = 2^256 - 0x1000003D1
*/
/* A field element f represents the sum(i=0..9, f.n[i] << (i*26)) mod p,
* where p is the field modulus, 2^256 - 2^32 - 977.
*
* The individual limbs f.n[i] can exceed 2^26; the field's magnitude roughly
* corresponds to how much excess is allowed. The value
* sum(i=0..9, f.n[i] << (i*26)) may exceed p, unless the field element is
* normalized. */
uint32_t n[10];
#ifdef VERIFY
int magnitude;
int normalized;
#endif
/*
* Magnitude m requires:
* n[i] <= 2 * m * (2^26 - 1) for i=0..8
* n[9] <= 2 * m * (2^22 - 1)
*
* Normalized requires:
* n[i] <= (2^26 - 1) for i=0..8
* sum(i=0..9, n[i] << (i*26)) < p
* (together these imply n[9] <= 2^22 - 1)
*/
SECP256K1_FE_VERIFY_FIELDS
} secp256k1_fe;
/* Unpacks a constant into a overlapping multi-limbed FE element. */
@@ -34,12 +47,6 @@ typedef struct {
(((uint32_t)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;

View File

@@ -12,47 +12,32 @@
#include "field.h"
#include "modinv32_impl.h"
/** See the comment at the top of field_5x52_impl.h for more details.
*
* Here, we represent field elements as 10 uint32_t's in base 2^26, least significant first,
* where limbs can contain >26 bits.
* A magnitude M means:
* - 2*M*(2^22-1) is the max (inclusive) of the most significant limb
* - 2*M*(2^26-1) is the max (inclusive) of the remaining limbs
*/
#ifdef VERIFY
static void secp256k1_fe_verify(const secp256k1_fe *a) {
static void secp256k1_fe_impl_verify(const secp256k1_fe *a) {
const uint32_t *d = a->n;
int m = a->normalized ? 1 : 2 * a->magnitude, r = 1;
r &= (d[0] <= 0x3FFFFFFUL * m);
r &= (d[1] <= 0x3FFFFFFUL * m);
r &= (d[2] <= 0x3FFFFFFUL * m);
r &= (d[3] <= 0x3FFFFFFUL * m);
r &= (d[4] <= 0x3FFFFFFUL * m);
r &= (d[5] <= 0x3FFFFFFUL * m);
r &= (d[6] <= 0x3FFFFFFUL * m);
r &= (d[7] <= 0x3FFFFFFUL * m);
r &= (d[8] <= 0x3FFFFFFUL * m);
r &= (d[9] <= 0x03FFFFFUL * m);
r &= (a->magnitude >= 0);
r &= (a->magnitude <= 32);
int m = a->normalized ? 1 : 2 * a->magnitude;
VERIFY_CHECK(d[0] <= 0x3FFFFFFUL * m);
VERIFY_CHECK(d[1] <= 0x3FFFFFFUL * m);
VERIFY_CHECK(d[2] <= 0x3FFFFFFUL * m);
VERIFY_CHECK(d[3] <= 0x3FFFFFFUL * m);
VERIFY_CHECK(d[4] <= 0x3FFFFFFUL * m);
VERIFY_CHECK(d[5] <= 0x3FFFFFFUL * m);
VERIFY_CHECK(d[6] <= 0x3FFFFFFUL * m);
VERIFY_CHECK(d[7] <= 0x3FFFFFFUL * m);
VERIFY_CHECK(d[8] <= 0x3FFFFFFUL * m);
VERIFY_CHECK(d[9] <= 0x03FFFFFUL * m);
if (a->normalized) {
r &= (a->magnitude <= 1);
if (r && (d[9] == 0x03FFFFFUL)) {
if (d[9] == 0x03FFFFFUL) {
uint32_t mid = d[8] & d[7] & d[6] & d[5] & d[4] & d[3] & d[2];
if (mid == 0x3FFFFFFUL) {
r &= ((d[1] + 0x40UL + ((d[0] + 0x3D1UL) >> 26)) <= 0x3FFFFFFUL);
VERIFY_CHECK((d[1] + 0x40UL + ((d[0] + 0x3D1UL) >> 26)) <= 0x3FFFFFFUL);
}
}
}
VERIFY_CHECK(r == 1);
}
#endif
static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m) {
VERIFY_CHECK(m >= 0);
VERIFY_CHECK(m <= 2048);
static void secp256k1_fe_impl_get_bounds(secp256k1_fe *r, int m) {
r->n[0] = 0x3FFFFFFUL * 2 * m;
r->n[1] = 0x3FFFFFFUL * 2 * m;
r->n[2] = 0x3FFFFFFUL * 2 * m;
@@ -63,14 +48,9 @@ static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m) {
r->n[7] = 0x3FFFFFFUL * 2 * m;
r->n[8] = 0x3FFFFFFUL * 2 * m;
r->n[9] = 0x03FFFFFUL * 2 * m;
#ifdef VERIFY
r->magnitude = m;
r->normalized = (m == 0);
secp256k1_fe_verify(r);
#endif
}
static void secp256k1_fe_normalize(secp256k1_fe *r) {
static void secp256k1_fe_impl_normalize(secp256k1_fe *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];
@@ -117,15 +97,9 @@ static void secp256k1_fe_normalize(secp256k1_fe *r) {
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9;
#ifdef VERIFY
r->magnitude = 1;
r->normalized = 1;
secp256k1_fe_verify(r);
#endif
}
static void secp256k1_fe_normalize_weak(secp256k1_fe *r) {
static void secp256k1_fe_impl_normalize_weak(secp256k1_fe *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];
@@ -149,14 +123,9 @@ static void secp256k1_fe_normalize_weak(secp256k1_fe *r) {
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9;
#ifdef VERIFY
r->magnitude = 1;
secp256k1_fe_verify(r);
#endif
}
static void secp256k1_fe_normalize_var(secp256k1_fe *r) {
static void secp256k1_fe_impl_normalize_var(secp256k1_fe *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];
@@ -204,15 +173,9 @@ static void secp256k1_fe_normalize_var(secp256k1_fe *r) {
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9;
#ifdef VERIFY
r->magnitude = 1;
r->normalized = 1;
secp256k1_fe_verify(r);
#endif
}
static int secp256k1_fe_normalizes_to_zero(const secp256k1_fe *r) {
static int secp256k1_fe_impl_normalizes_to_zero(const secp256k1_fe *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];
@@ -241,7 +204,7 @@ static int secp256k1_fe_normalizes_to_zero(const secp256k1_fe *r) {
return (z0 == 0) | (z1 == 0x3FFFFFFUL);
}
static int secp256k1_fe_normalizes_to_zero_var(const secp256k1_fe *r) {
static int secp256k1_fe_impl_normalizes_to_zero_var(const secp256k1_fe *r) {
uint32_t t0, t1, t2, t3, t4, t5, t6, t7, t8, t9;
uint32_t z0, z1;
uint32_t x;
@@ -293,53 +256,29 @@ static int secp256k1_fe_normalizes_to_zero_var(const secp256k1_fe *r) {
return (z0 == 0) | (z1 == 0x3FFFFFFUL);
}
SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) {
VERIFY_CHECK(0 <= a && a <= 0x7FFF);
SECP256K1_INLINE static void secp256k1_fe_impl_set_int(secp256k1_fe *r, int a) {
r->n[0] = a;
r->n[1] = r->n[2] = r->n[3] = r->n[4] = r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0;
#ifdef VERIFY
r->magnitude = (a != 0);
r->normalized = 1;
secp256k1_fe_verify(r);
#endif
}
SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe *a) {
SECP256K1_INLINE static int secp256k1_fe_impl_is_zero(const secp256k1_fe *a) {
const uint32_t *t = a->n;
#ifdef VERIFY
VERIFY_CHECK(a->normalized);
secp256k1_fe_verify(a);
#endif
return (t[0] | t[1] | t[2] | t[3] | t[4] | t[5] | t[6] | t[7] | t[8] | t[9]) == 0;
}
SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe *a) {
#ifdef VERIFY
VERIFY_CHECK(a->normalized);
secp256k1_fe_verify(a);
#endif
SECP256K1_INLINE static int secp256k1_fe_impl_is_odd(const secp256k1_fe *a) {
return a->n[0] & 1;
}
SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) {
SECP256K1_INLINE static void secp256k1_fe_impl_clear(secp256k1_fe *a) {
int i;
#ifdef VERIFY
a->magnitude = 0;
a->normalized = 1;
#endif
for (i=0; i<10; i++) {
a->n[i] = 0;
}
}
static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
static int secp256k1_fe_impl_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
int i;
#ifdef VERIFY
VERIFY_CHECK(a->normalized);
VERIFY_CHECK(b->normalized);
secp256k1_fe_verify(a);
secp256k1_fe_verify(b);
#endif
for (i = 9; i >= 0; i--) {
if (a->n[i] > b->n[i]) {
return 1;
@@ -351,8 +290,7 @@ static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
return 0;
}
static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) {
int ret;
static void secp256k1_fe_impl_set_b32_mod(secp256k1_fe *r, const unsigned char *a) {
r->n[0] = (uint32_t)a[31] | ((uint32_t)a[30] << 8) | ((uint32_t)a[29] << 16) | ((uint32_t)(a[28] & 0x3) << 24);
r->n[1] = (uint32_t)((a[28] >> 2) & 0x3f) | ((uint32_t)a[27] << 6) | ((uint32_t)a[26] << 14) | ((uint32_t)(a[25] & 0xf) << 22);
r->n[2] = (uint32_t)((a[25] >> 4) & 0xf) | ((uint32_t)a[24] << 4) | ((uint32_t)a[23] << 12) | ((uint32_t)(a[22] & 0x3f) << 20);
@@ -363,26 +301,15 @@ static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) {
r->n[7] = (uint32_t)((a[9] >> 6) & 0x3) | ((uint32_t)a[8] << 2) | ((uint32_t)a[7] << 10) | ((uint32_t)a[6] << 18);
r->n[8] = (uint32_t)a[5] | ((uint32_t)a[4] << 8) | ((uint32_t)a[3] << 16) | ((uint32_t)(a[2] & 0x3) << 24);
r->n[9] = (uint32_t)((a[2] >> 2) & 0x3f) | ((uint32_t)a[1] << 6) | ((uint32_t)a[0] << 14);
}
ret = !((r->n[9] == 0x3FFFFFUL) & ((r->n[8] & r->n[7] & r->n[6] & r->n[5] & r->n[4] & r->n[3] & r->n[2]) == 0x3FFFFFFUL) & ((r->n[1] + 0x40UL + ((r->n[0] + 0x3D1UL) >> 26)) > 0x3FFFFFFUL));
#ifdef VERIFY
r->magnitude = 1;
if (ret) {
r->normalized = 1;
secp256k1_fe_verify(r);
} else {
r->normalized = 0;
}
#endif
return ret;
static int secp256k1_fe_impl_set_b32_limit(secp256k1_fe *r, const unsigned char *a) {
secp256k1_fe_impl_set_b32_mod(r, a);
return !((r->n[9] == 0x3FFFFFUL) & ((r->n[8] & r->n[7] & r->n[6] & r->n[5] & r->n[4] & r->n[3] & r->n[2]) == 0x3FFFFFFUL) & ((r->n[1] + 0x40UL + ((r->n[0] + 0x3D1UL) >> 26)) > 0x3FFFFFFUL));
}
/** 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 *a) {
#ifdef VERIFY
VERIFY_CHECK(a->normalized);
secp256k1_fe_verify(a);
#endif
static void secp256k1_fe_impl_get_b32(unsigned char *r, const secp256k1_fe *a) {
r[0] = (a->n[9] >> 14) & 0xff;
r[1] = (a->n[9] >> 6) & 0xff;
r[2] = ((a->n[9] & 0x3F) << 2) | ((a->n[8] >> 24) & 0x3);
@@ -417,15 +344,15 @@ static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) {
r[31] = a->n[0] & 0xff;
}
SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) {
#ifdef VERIFY
VERIFY_CHECK(a->magnitude <= m);
secp256k1_fe_verify(a);
SECP256K1_INLINE static void secp256k1_fe_impl_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) {
/* For all legal values of m (0..31), the following properties hold: */
VERIFY_CHECK(0x3FFFC2FUL * 2 * (m + 1) >= 0x3FFFFFFUL * 2 * m);
VERIFY_CHECK(0x3FFFFBFUL * 2 * (m + 1) >= 0x3FFFFFFUL * 2 * m);
VERIFY_CHECK(0x3FFFFFFUL * 2 * (m + 1) >= 0x3FFFFFFUL * 2 * m);
VERIFY_CHECK(0x03FFFFFUL * 2 * (m + 1) >= 0x03FFFFFUL * 2 * m);
#endif
/* Due to the properties above, the left hand in the subtractions below is never less than
* the right hand. */
r->n[0] = 0x3FFFC2FUL * 2 * (m + 1) - a->n[0];
r->n[1] = 0x3FFFFBFUL * 2 * (m + 1) - a->n[1];
r->n[2] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[2];
@@ -436,14 +363,9 @@ SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k
r->n[7] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[7];
r->n[8] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[8];
r->n[9] = 0x03FFFFFUL * 2 * (m + 1) - a->n[9];
#ifdef VERIFY
r->magnitude = m + 1;
r->normalized = 0;
secp256k1_fe_verify(r);
#endif
}
SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) {
SECP256K1_INLINE static void secp256k1_fe_impl_mul_int(secp256k1_fe *r, int a) {
r->n[0] *= a;
r->n[1] *= a;
r->n[2] *= a;
@@ -454,17 +376,9 @@ SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) {
r->n[7] *= a;
r->n[8] *= a;
r->n[9] *= a;
#ifdef VERIFY
r->magnitude *= a;
r->normalized = 0;
secp256k1_fe_verify(r);
#endif
}
SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) {
#ifdef VERIFY
secp256k1_fe_verify(a);
#endif
SECP256K1_INLINE static void secp256k1_fe_impl_add(secp256k1_fe *r, const secp256k1_fe *a) {
r->n[0] += a->n[0];
r->n[1] += a->n[1];
r->n[2] += a->n[2];
@@ -475,25 +389,10 @@ SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_f
r->n[7] += a->n[7];
r->n[8] += a->n[8];
r->n[9] += a->n[9];
#ifdef VERIFY
r->magnitude += a->magnitude;
r->normalized = 0;
secp256k1_fe_verify(r);
#endif
}
SECP256K1_INLINE static void secp256k1_fe_add_int(secp256k1_fe *r, int a) {
#ifdef VERIFY
secp256k1_fe_verify(r);
VERIFY_CHECK(a >= 0);
VERIFY_CHECK(a <= 0x7FFF);
#endif
SECP256K1_INLINE static void secp256k1_fe_impl_add_int(secp256k1_fe *r, int a) {
r->n[0] += a;
#ifdef VERIFY
r->magnitude += 1;
r->normalized = 0;
secp256k1_fe_verify(r);
#endif
}
#if defined(USE_EXTERNAL_ASM)
@@ -1115,37 +1014,15 @@ SECP256K1_INLINE static void secp256k1_fe_sqr_inner(uint32_t *r, const uint32_t
}
#endif
static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) {
#ifdef VERIFY
VERIFY_CHECK(a->magnitude <= 8);
VERIFY_CHECK(b->magnitude <= 8);
secp256k1_fe_verify(a);
secp256k1_fe_verify(b);
VERIFY_CHECK(r != b);
VERIFY_CHECK(a != b);
#endif
SECP256K1_INLINE static void secp256k1_fe_impl_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) {
secp256k1_fe_mul_inner(r->n, a->n, b->n);
#ifdef VERIFY
r->magnitude = 1;
r->normalized = 0;
secp256k1_fe_verify(r);
#endif
}
static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) {
#ifdef VERIFY
VERIFY_CHECK(a->magnitude <= 8);
secp256k1_fe_verify(a);
#endif
SECP256K1_INLINE static void secp256k1_fe_impl_sqr(secp256k1_fe *r, const secp256k1_fe *a) {
secp256k1_fe_sqr_inner(r->n, a->n);
#ifdef VERIFY
r->magnitude = 1;
r->normalized = 0;
secp256k1_fe_verify(r);
#endif
}
static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) {
SECP256K1_INLINE static void secp256k1_fe_impl_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) {
uint32_t mask0, mask1;
volatile int vflag = flag;
SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n));
@@ -1161,25 +1038,14 @@ static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_
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);
#ifdef VERIFY
if (flag) {
r->magnitude = a->magnitude;
r->normalized = a->normalized;
}
#endif
}
static SECP256K1_INLINE void secp256k1_fe_half(secp256k1_fe *r) {
static SECP256K1_INLINE void secp256k1_fe_impl_half(secp256k1_fe *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];
uint32_t one = (uint32_t)1;
uint32_t mask = -(t0 & one) >> 6;
#ifdef VERIFY
secp256k1_fe_verify(r);
VERIFY_CHECK(r->magnitude < 32);
#endif
/* Bounds analysis (over the rationals).
*
* Let m = r->magnitude
@@ -1226,10 +1092,8 @@ static SECP256K1_INLINE void secp256k1_fe_half(secp256k1_fe *r) {
*
* Current bounds: t0..t8 <= C * (m/2 + 1/2)
* t9 <= D * (m/2 + 1/4)
*/
#ifdef VERIFY
/* Therefore the output magnitude (M) has to be set such that:
*
* Therefore the output magnitude (M) has to be set such that:
* t0..t8: C * M >= C * (m/2 + 1/2)
* t9: D * M >= D * (m/2 + 1/4)
*
@@ -1239,10 +1103,6 @@ static SECP256K1_INLINE void secp256k1_fe_half(secp256k1_fe *r) {
* and since we want the smallest such integer value for M:
* M == floor(m/2) + 1
*/
r->magnitude = (r->magnitude >> 1) + 1;
r->normalized = 0;
secp256k1_fe_verify(r);
#endif
}
static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) {
@@ -1261,10 +1121,7 @@ static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r,
r->n[7] = (r->n[7] & mask0) | (a->n[7] & mask1);
}
static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) {
#ifdef VERIFY
VERIFY_CHECK(a->normalized);
#endif
static void secp256k1_fe_impl_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) {
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;
@@ -1275,7 +1132,7 @@ static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe
r->n[7] = a->n[8] >> 16 | a->n[9] << 10;
}
static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a) {
static SECP256K1_INLINE void secp256k1_fe_impl_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *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);
@@ -1286,11 +1143,6 @@ static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const se
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;
secp256k1_fe_verify(r);
#endif
}
static void secp256k1_fe_from_signed30(secp256k1_fe *r, const secp256k1_modinv32_signed30 *a) {
@@ -1321,12 +1173,6 @@ static void secp256k1_fe_from_signed30(secp256k1_fe *r, const secp256k1_modinv32
r->n[7] = (a6 >> 2 ) & M26;
r->n[8] = (a6 >> 28 | a7 << 2) & M26;
r->n[9] = (a7 >> 24 | a8 << 6);
#ifdef VERIFY
r->magnitude = 1;
r->normalized = 1;
secp256k1_fe_verify(r);
#endif
}
static void secp256k1_fe_to_signed30(secp256k1_modinv32_signed30 *r, const secp256k1_fe *a) {
@@ -1334,10 +1180,6 @@ static void secp256k1_fe_to_signed30(secp256k1_modinv32_signed30 *r, const secp2
const uint64_t a0 = a->n[0], a1 = a->n[1], a2 = a->n[2], a3 = a->n[3], a4 = a->n[4],
a5 = a->n[5], a6 = a->n[6], a7 = a->n[7], a8 = a->n[8], a9 = a->n[9];
#ifdef VERIFY
VERIFY_CHECK(a->normalized);
#endif
r->v[0] = (a0 | a1 << 26) & M30;
r->v[1] = (a1 >> 4 | a2 << 22) & M30;
r->v[2] = (a2 >> 8 | a3 << 18) & M30;
@@ -1355,37 +1197,27 @@ static const secp256k1_modinv32_modinfo secp256k1_const_modinfo_fe = {
0x2DDACACFL
};
static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *x) {
secp256k1_fe tmp;
static void secp256k1_fe_impl_inv(secp256k1_fe *r, const secp256k1_fe *x) {
secp256k1_fe tmp = *x;
secp256k1_modinv32_signed30 s;
tmp = *x;
secp256k1_fe_normalize(&tmp);
secp256k1_fe_to_signed30(&s, &tmp);
secp256k1_modinv32(&s, &secp256k1_const_modinfo_fe);
secp256k1_fe_from_signed30(r, &s);
#ifdef VERIFY
VERIFY_CHECK(secp256k1_fe_normalizes_to_zero(r) == secp256k1_fe_normalizes_to_zero(&tmp));
#endif
}
static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *x) {
secp256k1_fe tmp;
static void secp256k1_fe_impl_inv_var(secp256k1_fe *r, const secp256k1_fe *x) {
secp256k1_fe tmp = *x;
secp256k1_modinv32_signed30 s;
tmp = *x;
secp256k1_fe_normalize_var(&tmp);
secp256k1_fe_to_signed30(&s, &tmp);
secp256k1_modinv32_var(&s, &secp256k1_const_modinfo_fe);
secp256k1_fe_from_signed30(r, &s);
#ifdef VERIFY
VERIFY_CHECK(secp256k1_fe_normalizes_to_zero(r) == secp256k1_fe_normalizes_to_zero(&tmp));
#endif
}
static int secp256k1_fe_is_square_var(const secp256k1_fe *x) {
static int secp256k1_fe_impl_is_square_var(const secp256k1_fe *x) {
secp256k1_fe tmp;
secp256k1_modinv32_signed30 s;
int jac, ret;
@@ -1403,10 +1235,6 @@ static int secp256k1_fe_is_square_var(const secp256k1_fe *x) {
secp256k1_fe dummy;
ret = secp256k1_fe_sqrt(&dummy, &tmp);
} else {
#ifdef VERIFY
secp256k1_fe dummy;
VERIFY_CHECK(jac == 2*secp256k1_fe_sqrt(&dummy, &tmp) - 1);
#endif
ret = jac >= 0;
}
return ret;

View File

@@ -9,15 +9,28 @@
#include <stdint.h>
/** This field implementation represents the value as 5 uint64_t limbs in base
* 2^52. */
typedef struct {
/* X = sum(i=0..4, n[i]*2^(i*52)) mod p
* where p = 2^256 - 0x1000003D1
*/
/* A field element f represents the sum(i=0..4, f.n[i] << (i*52)) mod p,
* where p is the field modulus, 2^256 - 2^32 - 977.
*
* The individual limbs f.n[i] can exceed 2^52; the field's magnitude roughly
* corresponds to how much excess is allowed. The value
* sum(i=0..4, f.n[i] << (i*52)) may exceed p, unless the field element is
* normalized. */
uint64_t n[5];
#ifdef VERIFY
int magnitude;
int normalized;
#endif
/*
* Magnitude m requires:
* n[i] <= 2 * m * (2^52 - 1) for i=0..3
* n[4] <= 2 * m * (2^48 - 1)
*
* Normalized requires:
* n[i] <= (2^52 - 1) for i=0..3
* sum(i=0..4, n[i] << (i*52)) < p
* (together these imply n[4] <= 2^48 - 1)
*/
SECP256K1_FE_VERIFY_FIELDS
} secp256k1_fe;
/* Unpacks a constant into a overlapping multi-limbed FE element. */
@@ -29,12 +42,6 @@ typedef struct {
((uint64_t)(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;

View File

@@ -14,6 +14,8 @@
#ifndef SECP256K1_FIELD_INNER5X52_IMPL_H
#define SECP256K1_FIELD_INNER5X52_IMPL_H
#include "util.h"
SECP256K1_INLINE static void secp256k1_fe_mul_inner(uint64_t *r, const uint64_t *a, const uint64_t * SECP256K1_RESTRICT b) {
/**
* Registers: rdx:rax = multiplication accumulator
@@ -278,7 +280,7 @@ __asm__ __volatile__(
"addq %%rsi,%%r8\n"
/* r[4] = c */
"movq %%r8,32(%%rdi)\n"
: "+S"(a), "=m"(tmp1), "=m"(tmp2), "=m"(tmp3)
: "+S"(a), "=&m"(tmp1), "=&m"(tmp2), "=&m"(tmp3)
: "b"(b), "D"(r)
: "%rax", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "cc", "memory"
);
@@ -493,7 +495,7 @@ __asm__ __volatile__(
"addq %%rsi,%%r8\n"
/* r[4] = c */
"movq %%r8,32(%%rdi)\n"
: "+S"(a), "=m"(tmp1), "=m"(tmp2), "=m"(tmp3)
: "+S"(a), "=&m"(tmp1), "=&m"(tmp2), "=&m"(tmp3)
: "D"(r)
: "%rax", "%rbx", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", "cc", "memory"
);

View File

@@ -18,59 +18,33 @@
#include "field_5x52_int128_impl.h"
#endif
/** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F,
* represented as 5 uint64_t's in base 2^52, least significant first. Note that the limbs are allowed to
* contain >52 bits each.
*
* Each field element has a 'magnitude' associated with it. Internally, a magnitude M means:
* - 2*M*(2^48-1) is the max (inclusive) of the most significant limb
* - 2*M*(2^52-1) is the max (inclusive) of the remaining limbs
*
* Operations have different rules for propagating magnitude to their outputs. If an operation takes a
* magnitude M as a parameter, that means the magnitude of input field elements can be at most M (inclusive).
*
* Each field element also has a 'normalized' flag. A field element is normalized if its magnitude is either
* 0 or 1, and its value is already reduced modulo the order of the field.
*/
#ifdef VERIFY
static void secp256k1_fe_verify(const secp256k1_fe *a) {
static void secp256k1_fe_impl_verify(const secp256k1_fe *a) {
const uint64_t *d = a->n;
int m = a->normalized ? 1 : 2 * a->magnitude, r = 1;
int m = a->normalized ? 1 : 2 * a->magnitude;
/* 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);
r &= (d[3] <= 0xFFFFFFFFFFFFFULL * m);
r &= (d[4] <= 0x0FFFFFFFFFFFFULL * m);
r &= (a->magnitude >= 0);
r &= (a->magnitude <= 2048);
VERIFY_CHECK(d[0] <= 0xFFFFFFFFFFFFFULL * m);
VERIFY_CHECK(d[1] <= 0xFFFFFFFFFFFFFULL * m);
VERIFY_CHECK(d[2] <= 0xFFFFFFFFFFFFFULL * m);
VERIFY_CHECK(d[3] <= 0xFFFFFFFFFFFFFULL * m);
VERIFY_CHECK(d[4] <= 0x0FFFFFFFFFFFFULL * m);
if (a->normalized) {
r &= (a->magnitude <= 1);
if (r && (d[4] == 0x0FFFFFFFFFFFFULL) && ((d[3] & d[2] & d[1]) == 0xFFFFFFFFFFFFFULL)) {
r &= (d[0] < 0xFFFFEFFFFFC2FULL);
if ((d[4] == 0x0FFFFFFFFFFFFULL) && ((d[3] & d[2] & d[1]) == 0xFFFFFFFFFFFFFULL)) {
VERIFY_CHECK(d[0] < 0xFFFFEFFFFFC2FULL);
}
}
VERIFY_CHECK(r == 1);
}
#endif
static void secp256k1_fe_get_bounds(secp256k1_fe *r, int m) {
VERIFY_CHECK(m >= 0);
VERIFY_CHECK(m <= 2048);
static void secp256k1_fe_impl_get_bounds(secp256k1_fe *r, int m) {
r->n[0] = 0xFFFFFFFFFFFFFULL * 2 * m;
r->n[1] = 0xFFFFFFFFFFFFFULL * 2 * m;
r->n[2] = 0xFFFFFFFFFFFFFULL * 2 * m;
r->n[3] = 0xFFFFFFFFFFFFFULL * 2 * m;
r->n[4] = 0x0FFFFFFFFFFFFULL * 2 * m;
#ifdef VERIFY
r->magnitude = m;
r->normalized = (m == 0);
secp256k1_fe_verify(r);
#endif
}
static void secp256k1_fe_normalize(secp256k1_fe *r) {
static void secp256k1_fe_impl_normalize(secp256k1_fe *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 */
@@ -105,15 +79,9 @@ static void secp256k1_fe_normalize(secp256k1_fe *r) {
t4 &= 0x0FFFFFFFFFFFFULL;
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
#ifdef VERIFY
r->magnitude = 1;
r->normalized = 1;
secp256k1_fe_verify(r);
#endif
}
static void secp256k1_fe_normalize_weak(secp256k1_fe *r) {
static void secp256k1_fe_impl_normalize_weak(secp256k1_fe *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 */
@@ -130,14 +98,9 @@ static void secp256k1_fe_normalize_weak(secp256k1_fe *r) {
VERIFY_CHECK(t4 >> 49 == 0);
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
#ifdef VERIFY
r->magnitude = 1;
secp256k1_fe_verify(r);
#endif
}
static void secp256k1_fe_normalize_var(secp256k1_fe *r) {
static void secp256k1_fe_impl_normalize_var(secp256k1_fe *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 */
@@ -173,15 +136,9 @@ static void secp256k1_fe_normalize_var(secp256k1_fe *r) {
}
r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
#ifdef VERIFY
r->magnitude = 1;
r->normalized = 1;
secp256k1_fe_verify(r);
#endif
}
static int secp256k1_fe_normalizes_to_zero(const secp256k1_fe *r) {
static int secp256k1_fe_impl_normalizes_to_zero(const secp256k1_fe *r) {
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
/* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */
@@ -204,7 +161,7 @@ static int secp256k1_fe_normalizes_to_zero(const secp256k1_fe *r) {
return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL);
}
static int secp256k1_fe_normalizes_to_zero_var(const secp256k1_fe *r) {
static int secp256k1_fe_impl_normalizes_to_zero_var(const secp256k1_fe *r) {
uint64_t t0, t1, t2, t3, t4;
uint64_t z0, z1;
uint64_t x;
@@ -245,53 +202,29 @@ static int secp256k1_fe_normalizes_to_zero_var(const secp256k1_fe *r) {
return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL);
}
SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) {
VERIFY_CHECK(0 <= a && a <= 0x7FFF);
SECP256K1_INLINE static void secp256k1_fe_impl_set_int(secp256k1_fe *r, int a) {
r->n[0] = a;
r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
#ifdef VERIFY
r->magnitude = (a != 0);
r->normalized = 1;
secp256k1_fe_verify(r);
#endif
}
SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe *a) {
SECP256K1_INLINE static int secp256k1_fe_impl_is_zero(const secp256k1_fe *a) {
const uint64_t *t = a->n;
#ifdef VERIFY
VERIFY_CHECK(a->normalized);
secp256k1_fe_verify(a);
#endif
return (t[0] | t[1] | t[2] | t[3] | t[4]) == 0;
}
SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe *a) {
#ifdef VERIFY
VERIFY_CHECK(a->normalized);
secp256k1_fe_verify(a);
#endif
SECP256K1_INLINE static int secp256k1_fe_impl_is_odd(const secp256k1_fe *a) {
return a->n[0] & 1;
}
SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) {
SECP256K1_INLINE static void secp256k1_fe_impl_clear(secp256k1_fe *a) {
int i;
#ifdef VERIFY
a->magnitude = 0;
a->normalized = 1;
#endif
for (i=0; i<5; i++) {
a->n[i] = 0;
}
}
static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
static int secp256k1_fe_impl_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
int i;
#ifdef VERIFY
VERIFY_CHECK(a->normalized);
VERIFY_CHECK(b->normalized);
secp256k1_fe_verify(a);
secp256k1_fe_verify(b);
#endif
for (i = 4; i >= 0; i--) {
if (a->n[i] > b->n[i]) {
return 1;
@@ -303,8 +236,7 @@ static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
return 0;
}
static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) {
int ret;
static void secp256k1_fe_impl_set_b32_mod(secp256k1_fe *r, const unsigned char *a) {
r->n[0] = (uint64_t)a[31]
| ((uint64_t)a[30] << 8)
| ((uint64_t)a[29] << 16)
@@ -339,25 +271,15 @@ static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) {
| ((uint64_t)a[2] << 24)
| ((uint64_t)a[1] << 32)
| ((uint64_t)a[0] << 40);
ret = !((r->n[4] == 0x0FFFFFFFFFFFFULL) & ((r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL) & (r->n[0] >= 0xFFFFEFFFFFC2FULL));
#ifdef VERIFY
r->magnitude = 1;
if (ret) {
r->normalized = 1;
secp256k1_fe_verify(r);
} else {
r->normalized = 0;
}
#endif
return ret;
}
static int secp256k1_fe_impl_set_b32_limit(secp256k1_fe *r, const unsigned char *a) {
secp256k1_fe_impl_set_b32_mod(r, a);
return !((r->n[4] == 0x0FFFFFFFFFFFFULL) & ((r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL) & (r->n[0] >= 0xFFFFEFFFFFC2FULL));
}
/** 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 *a) {
#ifdef VERIFY
VERIFY_CHECK(a->normalized);
secp256k1_fe_verify(a);
#endif
static void secp256k1_fe_impl_get_b32(unsigned char *r, const secp256k1_fe *a) {
r[0] = (a->n[4] >> 40) & 0xFF;
r[1] = (a->n[4] >> 32) & 0xFF;
r[2] = (a->n[4] >> 24) & 0xFF;
@@ -392,100 +314,50 @@ static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) {
r[31] = a->n[0] & 0xFF;
}
SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) {
#ifdef VERIFY
VERIFY_CHECK(a->magnitude <= m);
secp256k1_fe_verify(a);
SECP256K1_INLINE static void secp256k1_fe_impl_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) {
/* For all legal values of m (0..31), the following properties hold: */
VERIFY_CHECK(0xFFFFEFFFFFC2FULL * 2 * (m + 1) >= 0xFFFFFFFFFFFFFULL * 2 * m);
VERIFY_CHECK(0xFFFFFFFFFFFFFULL * 2 * (m + 1) >= 0xFFFFFFFFFFFFFULL * 2 * m);
VERIFY_CHECK(0x0FFFFFFFFFFFFULL * 2 * (m + 1) >= 0x0FFFFFFFFFFFFULL * 2 * m);
#endif
/* Due to the properties above, the left hand in the subtractions below is never less than
* the right hand. */
r->n[0] = 0xFFFFEFFFFFC2FULL * 2 * (m + 1) - a->n[0];
r->n[1] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[1];
r->n[2] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[2];
r->n[3] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[3];
r->n[4] = 0x0FFFFFFFFFFFFULL * 2 * (m + 1) - a->n[4];
#ifdef VERIFY
r->magnitude = m + 1;
r->normalized = 0;
secp256k1_fe_verify(r);
#endif
}
SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) {
SECP256K1_INLINE static void secp256k1_fe_impl_mul_int(secp256k1_fe *r, int a) {
r->n[0] *= a;
r->n[1] *= a;
r->n[2] *= a;
r->n[3] *= a;
r->n[4] *= a;
#ifdef VERIFY
r->magnitude *= a;
r->normalized = 0;
secp256k1_fe_verify(r);
#endif
}
SECP256K1_INLINE static void secp256k1_fe_add_int(secp256k1_fe *r, int a) {
#ifdef VERIFY
secp256k1_fe_verify(r);
VERIFY_CHECK(a >= 0);
VERIFY_CHECK(a <= 0x7FFF);
#endif
SECP256K1_INLINE static void secp256k1_fe_impl_add_int(secp256k1_fe *r, int a) {
r->n[0] += a;
#ifdef VERIFY
r->magnitude += 1;
r->normalized = 0;
secp256k1_fe_verify(r);
#endif
}
SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) {
#ifdef VERIFY
secp256k1_fe_verify(a);
#endif
SECP256K1_INLINE static void secp256k1_fe_impl_add(secp256k1_fe *r, const secp256k1_fe *a) {
r->n[0] += a->n[0];
r->n[1] += a->n[1];
r->n[2] += a->n[2];
r->n[3] += a->n[3];
r->n[4] += a->n[4];
#ifdef VERIFY
r->magnitude += a->magnitude;
r->normalized = 0;
secp256k1_fe_verify(r);
#endif
}
static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) {
#ifdef VERIFY
VERIFY_CHECK(a->magnitude <= 8);
VERIFY_CHECK(b->magnitude <= 8);
secp256k1_fe_verify(a);
secp256k1_fe_verify(b);
VERIFY_CHECK(r != b);
VERIFY_CHECK(a != b);
#endif
SECP256K1_INLINE static void secp256k1_fe_impl_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) {
secp256k1_fe_mul_inner(r->n, a->n, b->n);
#ifdef VERIFY
r->magnitude = 1;
r->normalized = 0;
secp256k1_fe_verify(r);
#endif
}
static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) {
#ifdef VERIFY
VERIFY_CHECK(a->magnitude <= 8);
secp256k1_fe_verify(a);
#endif
SECP256K1_INLINE static void secp256k1_fe_impl_sqr(secp256k1_fe *r, const secp256k1_fe *a) {
secp256k1_fe_sqr_inner(r->n, a->n);
#ifdef VERIFY
r->magnitude = 1;
r->normalized = 0;
secp256k1_fe_verify(r);
#endif
}
static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) {
SECP256K1_INLINE static void secp256k1_fe_impl_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) {
uint64_t mask0, mask1;
volatile int vflag = flag;
SECP256K1_CHECKMEM_CHECK_VERIFY(r->n, sizeof(r->n));
@@ -496,24 +368,13 @@ static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_
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);
#ifdef VERIFY
if (flag) {
r->magnitude = a->magnitude;
r->normalized = a->normalized;
}
#endif
}
static SECP256K1_INLINE void secp256k1_fe_half(secp256k1_fe *r) {
static SECP256K1_INLINE void secp256k1_fe_impl_half(secp256k1_fe *r) {
uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4];
uint64_t one = (uint64_t)1;
uint64_t mask = -(t0 & one) >> 12;
#ifdef VERIFY
secp256k1_fe_verify(r);
VERIFY_CHECK(r->magnitude < 32);
#endif
/* Bounds analysis (over the rationals).
*
* Let m = r->magnitude
@@ -550,10 +411,8 @@ static SECP256K1_INLINE void secp256k1_fe_half(secp256k1_fe *r) {
*
* Current bounds: t0..t3 <= C * (m/2 + 1/2)
* t4 <= D * (m/2 + 1/4)
*/
#ifdef VERIFY
/* Therefore the output magnitude (M) has to be set such that:
*
* Therefore the output magnitude (M) has to be set such that:
* t0..t3: C * M >= C * (m/2 + 1/2)
* t4: D * M >= D * (m/2 + 1/4)
*
@@ -563,10 +422,6 @@ static SECP256K1_INLINE void secp256k1_fe_half(secp256k1_fe *r) {
* and since we want the smallest such integer value for M:
* M == floor(m/2) + 1
*/
r->magnitude = (r->magnitude >> 1) + 1;
r->normalized = 0;
secp256k1_fe_verify(r);
#endif
}
static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) {
@@ -581,27 +436,19 @@ static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r,
r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1);
}
static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) {
#ifdef VERIFY
VERIFY_CHECK(a->normalized);
#endif
static void secp256k1_fe_impl_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) {
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 *r, const secp256k1_fe_storage *a) {
static SECP256K1_INLINE void secp256k1_fe_impl_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *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;
secp256k1_fe_verify(r);
#endif
}
static void secp256k1_fe_from_signed62(secp256k1_fe *r, const secp256k1_modinv64_signed62 *a) {
@@ -622,22 +469,12 @@ static void secp256k1_fe_from_signed62(secp256k1_fe *r, const secp256k1_modinv64
r->n[2] = (a1 >> 42 | a2 << 20) & M52;
r->n[3] = (a2 >> 32 | a3 << 30) & M52;
r->n[4] = (a3 >> 22 | a4 << 40);
#ifdef VERIFY
r->magnitude = 1;
r->normalized = 1;
secp256k1_fe_verify(r);
#endif
}
static void secp256k1_fe_to_signed62(secp256k1_modinv64_signed62 *r, const secp256k1_fe *a) {
const uint64_t M62 = UINT64_MAX >> 2;
const uint64_t a0 = a->n[0], a1 = a->n[1], a2 = a->n[2], a3 = a->n[3], a4 = a->n[4];
#ifdef VERIFY
VERIFY_CHECK(a->normalized);
#endif
r->v[0] = (a0 | a1 << 52) & M62;
r->v[1] = (a1 >> 10 | a2 << 42) & M62;
r->v[2] = (a2 >> 20 | a3 << 32) & M62;
@@ -650,37 +487,27 @@ static const secp256k1_modinv64_modinfo secp256k1_const_modinfo_fe = {
0x27C7F6E22DDACACFLL
};
static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *x) {
secp256k1_fe tmp;
static void secp256k1_fe_impl_inv(secp256k1_fe *r, const secp256k1_fe *x) {
secp256k1_fe tmp = *x;
secp256k1_modinv64_signed62 s;
tmp = *x;
secp256k1_fe_normalize(&tmp);
secp256k1_fe_to_signed62(&s, &tmp);
secp256k1_modinv64(&s, &secp256k1_const_modinfo_fe);
secp256k1_fe_from_signed62(r, &s);
#ifdef VERIFY
VERIFY_CHECK(secp256k1_fe_normalizes_to_zero(r) == secp256k1_fe_normalizes_to_zero(&tmp));
#endif
}
static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *x) {
secp256k1_fe tmp;
static void secp256k1_fe_impl_inv_var(secp256k1_fe *r, const secp256k1_fe *x) {
secp256k1_fe tmp = *x;
secp256k1_modinv64_signed62 s;
tmp = *x;
secp256k1_fe_normalize_var(&tmp);
secp256k1_fe_to_signed62(&s, &tmp);
secp256k1_modinv64_var(&s, &secp256k1_const_modinfo_fe);
secp256k1_fe_from_signed62(r, &s);
#ifdef VERIFY
VERIFY_CHECK(secp256k1_fe_normalizes_to_zero(r) == secp256k1_fe_normalizes_to_zero(&tmp));
#endif
}
static int secp256k1_fe_is_square_var(const secp256k1_fe *x) {
static int secp256k1_fe_impl_is_square_var(const secp256k1_fe *x) {
secp256k1_fe tmp;
secp256k1_modinv64_signed62 s;
int jac, ret;
@@ -698,10 +525,6 @@ static int secp256k1_fe_is_square_var(const secp256k1_fe *x) {
secp256k1_fe dummy;
ret = secp256k1_fe_sqrt(&dummy, &tmp);
} else {
#ifdef VERIFY
secp256k1_fe dummy;
VERIFY_CHECK(jac == 2*secp256k1_fe_sqrt(&dummy, &tmp) - 1);
#endif
ret = jac >= 0;
}
return ret;

View File

@@ -10,6 +10,7 @@
#include <stdint.h>
#include "int128.h"
#include "util.h"
#ifdef VERIFY
#define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0)

View File

@@ -7,6 +7,7 @@
#ifndef SECP256K1_FIELD_IMPL_H
#define SECP256K1_FIELD_IMPL_H
#include "field.h"
#include "util.h"
#if defined(SECP256K1_WIDEMUL_INT128)
@@ -19,6 +20,12 @@
SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe *a, const secp256k1_fe *b) {
secp256k1_fe na;
#ifdef VERIFY
secp256k1_fe_verify(a);
secp256k1_fe_verify(b);
VERIFY_CHECK(a->magnitude <= 1);
VERIFY_CHECK(b->magnitude <= 31);
#endif
secp256k1_fe_negate(&na, a, 1);
secp256k1_fe_add(&na, b);
return secp256k1_fe_normalizes_to_zero(&na);
@@ -26,6 +33,12 @@ SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe *a, const secp
SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe *a, const secp256k1_fe *b) {
secp256k1_fe na;
#ifdef VERIFY
secp256k1_fe_verify(a);
secp256k1_fe_verify(b);
VERIFY_CHECK(a->magnitude <= 1);
VERIFY_CHECK(b->magnitude <= 31);
#endif
secp256k1_fe_negate(&na, a, 1);
secp256k1_fe_add(&na, b);
return secp256k1_fe_normalizes_to_zero_var(&na);
@@ -42,9 +55,13 @@ static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a) {
* itself always a square (a ** ((p+1)/4) is the square of a ** ((p+1)/8)).
*/
secp256k1_fe x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1;
int j;
int j, ret;
#ifdef VERIFY
VERIFY_CHECK(r != a);
secp256k1_fe_verify(a);
VERIFY_CHECK(a->magnitude <= 8);
#endif
/** 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:
@@ -128,7 +145,288 @@ static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a) {
/* Check that a square root was actually calculated */
secp256k1_fe_sqr(&t1, r);
return secp256k1_fe_equal(&t1, a);
ret = secp256k1_fe_equal(&t1, a);
#ifdef VERIFY
if (!ret) {
secp256k1_fe_negate(&t1, &t1, 1);
secp256k1_fe_normalize_var(&t1);
VERIFY_CHECK(secp256k1_fe_equal_var(&t1, a));
}
#endif
return ret;
}
#ifndef VERIFY
static void secp256k1_fe_verify(const secp256k1_fe *a) { (void)a; }
#else
static void secp256k1_fe_impl_verify(const secp256k1_fe *a);
static void secp256k1_fe_verify(const secp256k1_fe *a) {
/* Magnitude between 0 and 32. */
VERIFY_CHECK((a->magnitude >= 0) && (a->magnitude <= 32));
/* Normalized is 0 or 1. */
VERIFY_CHECK((a->normalized == 0) || (a->normalized == 1));
/* If normalized, magnitude must be 0 or 1. */
if (a->normalized) VERIFY_CHECK(a->magnitude <= 1);
/* Invoke implementation-specific checks. */
secp256k1_fe_impl_verify(a);
}
static void secp256k1_fe_impl_normalize(secp256k1_fe *r);
SECP256K1_INLINE static void secp256k1_fe_normalize(secp256k1_fe *r) {
secp256k1_fe_verify(r);
secp256k1_fe_impl_normalize(r);
r->magnitude = 1;
r->normalized = 1;
secp256k1_fe_verify(r);
}
static void secp256k1_fe_impl_normalize_weak(secp256k1_fe *r);
SECP256K1_INLINE static void secp256k1_fe_normalize_weak(secp256k1_fe *r) {
secp256k1_fe_verify(r);
secp256k1_fe_impl_normalize_weak(r);
r->magnitude = 1;
secp256k1_fe_verify(r);
}
static void secp256k1_fe_impl_normalize_var(secp256k1_fe *r);
SECP256K1_INLINE static void secp256k1_fe_normalize_var(secp256k1_fe *r) {
secp256k1_fe_verify(r);
secp256k1_fe_impl_normalize_var(r);
r->magnitude = 1;
r->normalized = 1;
secp256k1_fe_verify(r);
}
static int secp256k1_fe_impl_normalizes_to_zero(const secp256k1_fe *r);
SECP256K1_INLINE static int secp256k1_fe_normalizes_to_zero(const secp256k1_fe *r) {
secp256k1_fe_verify(r);
return secp256k1_fe_impl_normalizes_to_zero(r);
}
static int secp256k1_fe_impl_normalizes_to_zero_var(const secp256k1_fe *r);
SECP256K1_INLINE static int secp256k1_fe_normalizes_to_zero_var(const secp256k1_fe *r) {
secp256k1_fe_verify(r);
return secp256k1_fe_impl_normalizes_to_zero_var(r);
}
static void secp256k1_fe_impl_set_int(secp256k1_fe *r, int a);
SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) {
VERIFY_CHECK(0 <= a && a <= 0x7FFF);
secp256k1_fe_impl_set_int(r, a);
r->magnitude = (a != 0);
r->normalized = 1;
secp256k1_fe_verify(r);
}
static void secp256k1_fe_impl_add_int(secp256k1_fe *r, int a);
SECP256K1_INLINE static void secp256k1_fe_add_int(secp256k1_fe *r, int a) {
VERIFY_CHECK(0 <= a && a <= 0x7FFF);
secp256k1_fe_verify(r);
secp256k1_fe_impl_add_int(r, a);
r->magnitude += 1;
r->normalized = 0;
secp256k1_fe_verify(r);
}
static void secp256k1_fe_impl_clear(secp256k1_fe *a);
SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) {
a->magnitude = 0;
a->normalized = 1;
secp256k1_fe_impl_clear(a);
secp256k1_fe_verify(a);
}
static int secp256k1_fe_impl_is_zero(const secp256k1_fe *a);
SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe *a) {
secp256k1_fe_verify(a);
VERIFY_CHECK(a->normalized);
return secp256k1_fe_impl_is_zero(a);
}
static int secp256k1_fe_impl_is_odd(const secp256k1_fe *a);
SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe *a) {
secp256k1_fe_verify(a);
VERIFY_CHECK(a->normalized);
return secp256k1_fe_impl_is_odd(a);
}
static int secp256k1_fe_impl_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b);
SECP256K1_INLINE static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) {
secp256k1_fe_verify(a);
secp256k1_fe_verify(b);
VERIFY_CHECK(a->normalized);
VERIFY_CHECK(b->normalized);
return secp256k1_fe_impl_cmp_var(a, b);
}
static void secp256k1_fe_impl_set_b32_mod(secp256k1_fe *r, const unsigned char *a);
SECP256K1_INLINE static void secp256k1_fe_set_b32_mod(secp256k1_fe *r, const unsigned char *a) {
secp256k1_fe_impl_set_b32_mod(r, a);
r->magnitude = 1;
r->normalized = 0;
secp256k1_fe_verify(r);
}
static int secp256k1_fe_impl_set_b32_limit(secp256k1_fe *r, const unsigned char *a);
SECP256K1_INLINE static int secp256k1_fe_set_b32_limit(secp256k1_fe *r, const unsigned char *a) {
if (secp256k1_fe_impl_set_b32_limit(r, a)) {
r->magnitude = 1;
r->normalized = 1;
secp256k1_fe_verify(r);
return 1;
} else {
/* Mark the output field element as invalid. */
r->magnitude = -1;
return 0;
}
}
static void secp256k1_fe_impl_get_b32(unsigned char *r, const secp256k1_fe *a);
SECP256K1_INLINE static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) {
secp256k1_fe_verify(a);
VERIFY_CHECK(a->normalized);
secp256k1_fe_impl_get_b32(r, a);
}
static void secp256k1_fe_impl_negate(secp256k1_fe *r, const secp256k1_fe *a, int m);
SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) {
secp256k1_fe_verify(a);
VERIFY_CHECK(m >= 0 && m <= 31);
VERIFY_CHECK(a->magnitude <= m);
secp256k1_fe_impl_negate(r, a, m);
r->magnitude = m + 1;
r->normalized = 0;
secp256k1_fe_verify(r);
}
static void secp256k1_fe_impl_mul_int(secp256k1_fe *r, int a);
SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) {
secp256k1_fe_verify(r);
VERIFY_CHECK(a >= 0 && a <= 32);
VERIFY_CHECK(a*r->magnitude <= 32);
secp256k1_fe_impl_mul_int(r, a);
r->magnitude *= a;
r->normalized = 0;
secp256k1_fe_verify(r);
}
static void secp256k1_fe_impl_add(secp256k1_fe *r, const secp256k1_fe *a);
SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) {
secp256k1_fe_verify(r);
secp256k1_fe_verify(a);
VERIFY_CHECK(r->magnitude + a->magnitude <= 32);
secp256k1_fe_impl_add(r, a);
r->magnitude += a->magnitude;
r->normalized = 0;
secp256k1_fe_verify(r);
}
static void secp256k1_fe_impl_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b);
SECP256K1_INLINE static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) {
secp256k1_fe_verify(a);
secp256k1_fe_verify(b);
VERIFY_CHECK(a->magnitude <= 8);
VERIFY_CHECK(b->magnitude <= 8);
VERIFY_CHECK(r != b);
VERIFY_CHECK(a != b);
secp256k1_fe_impl_mul(r, a, b);
r->magnitude = 1;
r->normalized = 0;
secp256k1_fe_verify(r);
}
static void secp256k1_fe_impl_sqr(secp256k1_fe *r, const secp256k1_fe *a);
SECP256K1_INLINE static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) {
secp256k1_fe_verify(a);
VERIFY_CHECK(a->magnitude <= 8);
secp256k1_fe_impl_sqr(r, a);
r->magnitude = 1;
r->normalized = 0;
secp256k1_fe_verify(r);
}
static void secp256k1_fe_impl_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag);
SECP256K1_INLINE static void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) {
VERIFY_CHECK(flag == 0 || flag == 1);
secp256k1_fe_verify(a);
secp256k1_fe_verify(r);
secp256k1_fe_impl_cmov(r, a, flag);
if (flag) {
r->magnitude = a->magnitude;
r->normalized = a->normalized;
}
secp256k1_fe_verify(r);
}
static void secp256k1_fe_impl_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a);
SECP256K1_INLINE static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) {
secp256k1_fe_verify(a);
VERIFY_CHECK(a->normalized);
secp256k1_fe_impl_to_storage(r, a);
}
static void secp256k1_fe_impl_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a);
SECP256K1_INLINE static void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a) {
secp256k1_fe_impl_from_storage(r, a);
r->magnitude = 1;
r->normalized = 1;
secp256k1_fe_verify(r);
}
static void secp256k1_fe_impl_inv(secp256k1_fe *r, const secp256k1_fe *x);
SECP256K1_INLINE static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *x) {
int input_is_zero = secp256k1_fe_normalizes_to_zero(x);
secp256k1_fe_verify(x);
secp256k1_fe_impl_inv(r, x);
r->magnitude = x->magnitude > 0;
r->normalized = 1;
VERIFY_CHECK(secp256k1_fe_normalizes_to_zero(r) == input_is_zero);
secp256k1_fe_verify(r);
}
static void secp256k1_fe_impl_inv_var(secp256k1_fe *r, const secp256k1_fe *x);
SECP256K1_INLINE static void secp256k1_fe_inv_var(secp256k1_fe *r, const secp256k1_fe *x) {
int input_is_zero = secp256k1_fe_normalizes_to_zero(x);
secp256k1_fe_verify(x);
secp256k1_fe_impl_inv_var(r, x);
r->magnitude = x->magnitude > 0;
r->normalized = 1;
VERIFY_CHECK(secp256k1_fe_normalizes_to_zero(r) == input_is_zero);
secp256k1_fe_verify(r);
}
static int secp256k1_fe_impl_is_square_var(const secp256k1_fe *x);
SECP256K1_INLINE static int secp256k1_fe_is_square_var(const secp256k1_fe *x) {
int ret;
secp256k1_fe tmp = *x, sqrt;
secp256k1_fe_verify(x);
ret = secp256k1_fe_impl_is_square_var(x);
secp256k1_fe_normalize_weak(&tmp);
VERIFY_CHECK(ret == secp256k1_fe_sqrt(&sqrt, &tmp));
return ret;
}
static void secp256k1_fe_impl_get_bounds(secp256k1_fe* r, int m);
SECP256K1_INLINE static void secp256k1_fe_get_bounds(secp256k1_fe* r, int m) {
VERIFY_CHECK(m >= 0);
VERIFY_CHECK(m <= 32);
secp256k1_fe_impl_get_bounds(r, m);
r->magnitude = m;
r->normalized = (m == 0);
secp256k1_fe_verify(r);
}
static void secp256k1_fe_impl_half(secp256k1_fe *r);
SECP256K1_INLINE static void secp256k1_fe_half(secp256k1_fe *r) {
secp256k1_fe_verify(r);
VERIFY_CHECK(r->magnitude < 32);
secp256k1_fe_impl_half(r);
r->magnitude = (r->magnitude >> 1) + 1;
r->normalized = 0;
secp256k1_fe_verify(r);
}
#endif /* defined(VERIFY) */
#endif /* SECP256K1_FIELD_IMPL_H */

View File

@@ -164,4 +164,10 @@ static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *b);
*/
static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge);
/** Check invariants on an affine group element (no-op unless VERIFY is enabled). */
static void secp256k1_ge_verify(const secp256k1_ge *a);
/** Check invariants on a Jacobian group element (no-op unless VERIFY is enabled). */
static void secp256k1_gej_verify(const secp256k1_gej *a);
#endif /* SECP256K1_GROUP_H */

View File

@@ -9,6 +9,7 @@
#include "field.h"
#include "group.h"
#include "util.h"
/* Begin of section generated by sage/gen_exhaustive_groups.sage. */
#define SECP256K1_G_ORDER_7 SECP256K1_GE_CONST(\
@@ -72,37 +73,80 @@ static const secp256k1_ge secp256k1_ge_const_g = SECP256K1_G;
#endif
/* End of section generated by sage/gen_exhaustive_groups.sage. */
static const secp256k1_fe secp256k1_fe_const_b = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, SECP256K1_B);
static void secp256k1_ge_verify(const secp256k1_ge *a) {
#ifdef VERIFY
secp256k1_fe_verify(&a->x);
secp256k1_fe_verify(&a->y);
VERIFY_CHECK(a->infinity == 0 || a->infinity == 1);
#endif
(void)a;
}
static void secp256k1_gej_verify(const secp256k1_gej *a) {
#ifdef VERIFY
secp256k1_fe_verify(&a->x);
secp256k1_fe_verify(&a->y);
secp256k1_fe_verify(&a->z);
VERIFY_CHECK(a->infinity == 0 || a->infinity == 1);
#endif
(void)a;
}
/* Set r to the affine coordinates of Jacobian point (a.x, a.y, 1/zi). */
static void secp256k1_ge_set_gej_zinv(secp256k1_ge *r, const secp256k1_gej *a, const secp256k1_fe *zi) {
secp256k1_fe zi2;
secp256k1_fe zi3;
secp256k1_gej_verify(a);
secp256k1_fe_verify(zi);
VERIFY_CHECK(!a->infinity);
secp256k1_fe_sqr(&zi2, zi);
secp256k1_fe_mul(&zi3, &zi2, zi);
secp256k1_fe_mul(&r->x, &a->x, &zi2);
secp256k1_fe_mul(&r->y, &a->y, &zi3);
r->infinity = a->infinity;
secp256k1_ge_verify(r);
}
/* Set r to the affine coordinates of Jacobian point (a.x, a.y, 1/zi). */
static void secp256k1_ge_set_ge_zinv(secp256k1_ge *r, const secp256k1_ge *a, const secp256k1_fe *zi) {
secp256k1_fe zi2;
secp256k1_fe zi3;
secp256k1_ge_verify(a);
secp256k1_fe_verify(zi);
VERIFY_CHECK(!a->infinity);
secp256k1_fe_sqr(&zi2, zi);
secp256k1_fe_mul(&zi3, &zi2, zi);
secp256k1_fe_mul(&r->x, &a->x, &zi2);
secp256k1_fe_mul(&r->y, &a->y, &zi3);
r->infinity = a->infinity;
secp256k1_ge_verify(r);
}
static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y) {
secp256k1_fe_verify(x);
secp256k1_fe_verify(y);
r->infinity = 0;
r->x = *x;
r->y = *y;
secp256k1_ge_verify(r);
}
static int secp256k1_ge_is_infinity(const secp256k1_ge *a) {
secp256k1_ge_verify(a);
return a->infinity;
}
static void secp256k1_ge_neg(secp256k1_ge *r, const secp256k1_ge *a) {
secp256k1_ge_verify(a);
*r = *a;
secp256k1_fe_normalize_weak(&r->y);
secp256k1_fe_negate(&r->y, &r->y, 1);
secp256k1_ge_verify(r);
}
static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a) {
secp256k1_fe z2, z3;
secp256k1_gej_verify(a);
r->infinity = a->infinity;
secp256k1_fe_inv(&a->z, &a->z);
secp256k1_fe_sqr(&z2, &a->z);
@@ -112,14 +156,17 @@ static void secp256k1_ge_set_gej(secp256k1_ge *r, secp256k1_gej *a) {
secp256k1_fe_set_int(&a->z, 1);
r->x = a->x;
r->y = a->y;
secp256k1_ge_verify(r);
}
static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) {
secp256k1_fe z2, z3;
if (a->infinity) {
secp256k1_gej_verify(a);
if (secp256k1_gej_is_infinity(a)) {
secp256k1_ge_set_infinity(r);
return;
}
r->infinity = 0;
secp256k1_fe_inv_var(&a->z, &a->z);
secp256k1_fe_sqr(&z2, &a->z);
secp256k1_fe_mul(&z3, &a->z, &z2);
@@ -127,6 +174,7 @@ static void secp256k1_ge_set_gej_var(secp256k1_ge *r, secp256k1_gej *a) {
secp256k1_fe_mul(&a->y, &a->y, &z3);
secp256k1_fe_set_int(&a->z, 1);
secp256k1_ge_set_xy(r, &a->x, &a->y);
secp256k1_ge_verify(r);
}
static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a, size_t len) {
@@ -135,6 +183,7 @@ static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a
size_t last_i = SIZE_MAX;
for (i = 0; i < len; i++) {
secp256k1_gej_verify(&a[i]);
if (a[i].infinity) {
secp256k1_ge_set_infinity(&r[i]);
} else {
@@ -168,6 +217,7 @@ static void secp256k1_ge_set_all_gej_var(secp256k1_ge *r, const secp256k1_gej *a
if (!a[i].infinity) {
secp256k1_ge_set_gej_zinv(&r[i], &a[i], &r[i].x);
}
secp256k1_ge_verify(&r[i]);
}
}
@@ -176,21 +226,25 @@ static void secp256k1_ge_table_set_globalz(size_t len, secp256k1_ge *a, const se
secp256k1_fe zs;
if (len > 0) {
/* Verify inputs a[len-1] and zr[len-1]. */
secp256k1_ge_verify(&a[i]);
secp256k1_fe_verify(&zr[i]);
/* Ensure all y values are in weak normal form for fast negation of points */
secp256k1_fe_normalize_weak(&a[i].y);
zs = zr[i];
/* Work our way backwards, using the z-ratios to scale the x/y values. */
while (i > 0) {
secp256k1_gej tmpa;
/* Verify all inputs a[i] and zr[i]. */
secp256k1_fe_verify(&zr[i]);
secp256k1_ge_verify(&a[i]);
if (i != len - 1) {
secp256k1_fe_mul(&zs, &zs, &zr[i]);
}
i--;
tmpa.x = a[i].x;
tmpa.y = a[i].y;
tmpa.infinity = 0;
secp256k1_ge_set_gej_zinv(&a[i], &tmpa, &zs);
secp256k1_ge_set_ge_zinv(&a[i], &a[i], &zs);
/* Verify the output a[i]. */
secp256k1_ge_verify(&a[i]);
}
}
}
@@ -200,12 +254,14 @@ static void secp256k1_gej_set_infinity(secp256k1_gej *r) {
secp256k1_fe_clear(&r->x);
secp256k1_fe_clear(&r->y);
secp256k1_fe_clear(&r->z);
secp256k1_gej_verify(r);
}
static void secp256k1_ge_set_infinity(secp256k1_ge *r) {
r->infinity = 1;
secp256k1_fe_clear(&r->x);
secp256k1_fe_clear(&r->y);
secp256k1_ge_verify(r);
}
static void secp256k1_gej_clear(secp256k1_gej *r) {
@@ -223,31 +279,35 @@ static void secp256k1_ge_clear(secp256k1_ge *r) {
static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) {
secp256k1_fe x2, x3;
int ret;
secp256k1_fe_verify(x);
r->x = *x;
secp256k1_fe_sqr(&x2, x);
secp256k1_fe_mul(&x3, x, &x2);
r->infinity = 0;
secp256k1_fe_add_int(&x3, SECP256K1_B);
if (!secp256k1_fe_sqrt(&r->y, &x3)) {
return 0;
}
ret = secp256k1_fe_sqrt(&r->y, &x3);
secp256k1_fe_normalize_var(&r->y);
if (secp256k1_fe_is_odd(&r->y) != odd) {
secp256k1_fe_negate(&r->y, &r->y, 1);
}
return 1;
secp256k1_ge_verify(r);
return ret;
}
static void secp256k1_gej_set_ge(secp256k1_gej *r, const secp256k1_ge *a) {
secp256k1_ge_verify(a);
r->infinity = a->infinity;
r->x = a->x;
r->y = a->y;
secp256k1_fe_set_int(&r->z, 1);
secp256k1_gej_verify(r);
}
static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b) {
secp256k1_gej tmp;
secp256k1_gej_verify(b);
secp256k1_gej_verify(a);
secp256k1_gej_neg(&tmp, a);
secp256k1_gej_add_var(&tmp, &tmp, b, NULL);
return secp256k1_gej_is_infinity(&tmp);
@@ -255,6 +315,8 @@ static int secp256k1_gej_eq_var(const secp256k1_gej *a, const secp256k1_gej *b)
static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a) {
secp256k1_fe r, r2;
secp256k1_fe_verify(x);
secp256k1_gej_verify(a);
VERIFY_CHECK(!a->infinity);
secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x);
r2 = a->x; secp256k1_fe_normalize_weak(&r2);
@@ -262,20 +324,24 @@ static int secp256k1_gej_eq_x_var(const secp256k1_fe *x, const secp256k1_gej *a)
}
static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a) {
secp256k1_gej_verify(a);
r->infinity = a->infinity;
r->x = a->x;
r->y = a->y;
r->z = a->z;
secp256k1_fe_normalize_weak(&r->y);
secp256k1_fe_negate(&r->y, &r->y, 1);
secp256k1_gej_verify(r);
}
static int secp256k1_gej_is_infinity(const secp256k1_gej *a) {
secp256k1_gej_verify(a);
return a->infinity;
}
static int secp256k1_ge_is_valid_var(const secp256k1_ge *a) {
secp256k1_fe y2, x3;
secp256k1_ge_verify(a);
if (a->infinity) {
return 0;
}
@@ -291,6 +357,7 @@ static SECP256K1_INLINE void secp256k1_gej_double(secp256k1_gej *r, const secp25
/* Operations: 3 mul, 4 sqr, 8 add/half/mul_int/negate */
secp256k1_fe l, s, t;
secp256k1_gej_verify(a);
r->infinity = a->infinity;
/* Formula used:
@@ -317,6 +384,7 @@ static SECP256K1_INLINE void secp256k1_gej_double(secp256k1_gej *r, const secp25
secp256k1_fe_mul(&r->y, &t, &l); /* Y3 = L*(X3 + T) (1) */
secp256k1_fe_add(&r->y, &s); /* Y3 = L*(X3 + T) + S^2 (2) */
secp256k1_fe_negate(&r->y, &r->y, 2); /* Y3 = -(L*(X3 + T) + S^2) (3) */
secp256k1_gej_verify(r);
}
static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr) {
@@ -330,6 +398,7 @@ static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, s
* the infinity flag even though the point doubles to infinity, and the result
* point will be gibberish (z = 0 but infinity = 0).
*/
secp256k1_gej_verify(a);
if (a->infinity) {
secp256k1_gej_set_infinity(r);
if (rzr != NULL) {
@@ -344,12 +413,15 @@ static void secp256k1_gej_double_var(secp256k1_gej *r, const secp256k1_gej *a, s
}
secp256k1_gej_double(r, a);
secp256k1_gej_verify(r);
}
static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_gej *b, secp256k1_fe *rzr) {
/* 12 mul, 4 sqr, 11 add/negate/normalizes_to_zero (ignoring special cases) */
secp256k1_fe z22, z12, u1, u2, s1, s2, h, i, h2, h3, t;
secp256k1_gej_verify(a);
secp256k1_gej_verify(b);
if (a->infinity) {
VERIFY_CHECK(rzr == NULL);
*r = *b;
@@ -404,11 +476,14 @@ static void secp256k1_gej_add_var(secp256k1_gej *r, const secp256k1_gej *a, cons
secp256k1_fe_mul(&r->y, &t, &i);
secp256k1_fe_mul(&h3, &h3, &s1);
secp256k1_fe_add(&r->y, &h3);
secp256k1_gej_verify(r);
}
static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, secp256k1_fe *rzr) {
/* 8 mul, 3 sqr, 13 add/negate/normalize_weak/normalizes_to_zero (ignoring special cases) */
secp256k1_fe z12, u1, u2, s1, s2, h, i, h2, h3, t;
secp256k1_gej_verify(a);
secp256k1_ge_verify(b);
if (a->infinity) {
VERIFY_CHECK(rzr == NULL);
secp256k1_gej_set_ge(r, b);
@@ -461,12 +536,16 @@ static void secp256k1_gej_add_ge_var(secp256k1_gej *r, const secp256k1_gej *a, c
secp256k1_fe_mul(&r->y, &t, &i);
secp256k1_fe_mul(&h3, &h3, &s1);
secp256k1_fe_add(&r->y, &h3);
secp256k1_gej_verify(r);
if (rzr != NULL) secp256k1_fe_verify(rzr);
}
static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a, const secp256k1_ge *b, const secp256k1_fe *bzinv) {
/* 9 mul, 3 sqr, 13 add/negate/normalize_weak/normalizes_to_zero (ignoring special cases) */
secp256k1_fe az, z12, u1, u2, s1, s2, h, i, h2, h3, t;
secp256k1_ge_verify(b);
secp256k1_fe_verify(bzinv);
if (a->infinity) {
secp256k1_fe bzinv2, bzinv3;
r->infinity = b->infinity;
@@ -525,6 +604,7 @@ static void secp256k1_gej_add_zinv_var(secp256k1_gej *r, const secp256k1_gej *a,
secp256k1_fe_mul(&r->y, &t, &i);
secp256k1_fe_mul(&h3, &h3, &s1);
secp256k1_fe_add(&r->y, &h3);
secp256k1_gej_verify(r);
}
@@ -533,6 +613,8 @@ static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const
secp256k1_fe zz, u1, u2, s1, s2, t, tt, m, n, q, rr;
secp256k1_fe m_alt, rr_alt;
int degenerate;
secp256k1_gej_verify(a);
secp256k1_ge_verify(b);
VERIFY_CHECK(!b->infinity);
VERIFY_CHECK(a->infinity == 0 || a->infinity == 1);
@@ -658,21 +740,28 @@ static void secp256k1_gej_add_ge(secp256k1_gej *r, const secp256k1_gej *a, const
* We have degenerate = false, r->z = (y1 + y2) * Z.
* Then r->infinity = ((y1 + y2)Z == 0) = (y1 == -y2) = false. */
r->infinity = secp256k1_fe_normalizes_to_zero(&r->z);
secp256k1_gej_verify(r);
}
static void secp256k1_gej_rescale(secp256k1_gej *r, const secp256k1_fe *s) {
/* Operations: 4 mul, 1 sqr */
secp256k1_fe zz;
VERIFY_CHECK(!secp256k1_fe_is_zero(s));
secp256k1_gej_verify(r);
secp256k1_fe_verify(s);
#ifdef VERIFY
VERIFY_CHECK(!secp256k1_fe_normalizes_to_zero_var(s));
#endif
secp256k1_fe_sqr(&zz, s);
secp256k1_fe_mul(&r->x, &r->x, &zz); /* r->x *= s^2 */
secp256k1_fe_mul(&r->y, &r->y, &zz);
secp256k1_fe_mul(&r->y, &r->y, s); /* r->y *= s^3 */
secp256k1_fe_mul(&r->z, &r->z, s); /* r->z *= s */
secp256k1_gej_verify(r);
}
static void secp256k1_ge_to_storage(secp256k1_ge_storage *r, const secp256k1_ge *a) {
secp256k1_fe x, y;
secp256k1_ge_verify(a);
VERIFY_CHECK(!a->infinity);
x = a->x;
secp256k1_fe_normalize(&x);
@@ -686,14 +775,18 @@ static void secp256k1_ge_from_storage(secp256k1_ge *r, const secp256k1_ge_storag
secp256k1_fe_from_storage(&r->x, &a->x);
secp256k1_fe_from_storage(&r->y, &a->y);
r->infinity = 0;
secp256k1_ge_verify(r);
}
static SECP256K1_INLINE void secp256k1_gej_cmov(secp256k1_gej *r, const secp256k1_gej *a, int flag) {
secp256k1_gej_verify(r);
secp256k1_gej_verify(a);
secp256k1_fe_cmov(&r->x, &a->x, flag);
secp256k1_fe_cmov(&r->y, &a->y, flag);
secp256k1_fe_cmov(&r->z, &a->z, flag);
r->infinity ^= (r->infinity ^ a->infinity) & flag;
secp256k1_gej_verify(r);
}
static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r, const secp256k1_ge_storage *a, int flag) {
@@ -703,7 +796,9 @@ static SECP256K1_INLINE void secp256k1_ge_storage_cmov(secp256k1_ge_storage *r,
static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) {
*r = *a;
secp256k1_ge_verify(a);
secp256k1_fe_mul(&r->x, &r->x, &secp256k1_const_beta);
secp256k1_ge_verify(r);
}
static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge) {
@@ -711,6 +806,7 @@ static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge) {
secp256k1_gej out;
int i;
secp256k1_ge_verify(ge);
/* A very simple EC multiplication ladder that avoids a dependency on ecmult. */
secp256k1_gej_set_infinity(&out);
for (i = 0; i < 32; ++i) {

View File

@@ -2,6 +2,7 @@
#define SECP256K1_INT128_NATIVE_IMPL_H
#include "int128.h"
#include "util.h"
static SECP256K1_INLINE void secp256k1_u128_load(secp256k1_uint128 *r, uint64_t hi, uint64_t lo) {
*r = (((uint128_t)hi) << 64) + lo;

View File

@@ -2,6 +2,7 @@
#define SECP256K1_INT128_STRUCT_IMPL_H
#include "int128.h"
#include "util.h"
#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_ARM64)) /* MSVC */
# include <intrin.h>

View File

@@ -64,7 +64,7 @@ static void secp256k1_modinv32_normalize_30(secp256k1_modinv32_signed30 *r, int3
const int32_t M30 = (int32_t)(UINT32_MAX >> 2);
int32_t r0 = r->v[0], r1 = r->v[1], r2 = r->v[2], r3 = r->v[3], r4 = r->v[4],
r5 = r->v[5], r6 = r->v[6], r7 = r->v[7], r8 = r->v[8];
int32_t cond_add, cond_negate;
volatile int32_t cond_add, cond_negate;
#ifdef VERIFY
/* Verify that all limbs are in range (-2^30,2^30). */
@@ -186,7 +186,8 @@ static int32_t secp256k1_modinv32_divsteps_30(int32_t zeta, uint32_t f0, uint32_
* being inside [-2^31,2^31) means that casting to signed works correctly.
*/
uint32_t u = 1, v = 0, q = 0, r = 1;
uint32_t c1, c2, f = f0, g = g0, x, y, z;
volatile uint32_t c1, c2;
uint32_t mask1, mask2, f = f0, g = g0, x, y, z;
int i;
for (i = 0; i < 30; ++i) {
@@ -195,23 +196,25 @@ static int32_t secp256k1_modinv32_divsteps_30(int32_t zeta, uint32_t f0, uint32_
VERIFY_CHECK((q * f0 + r * g0) == g << i);
/* Compute conditional masks for (zeta < 0) and for (g & 1). */
c1 = zeta >> 31;
c2 = -(g & 1);
mask1 = c1;
c2 = g & 1;
mask2 = -c2;
/* Compute x,y,z, conditionally negated versions of f,u,v. */
x = (f ^ c1) - c1;
y = (u ^ c1) - c1;
z = (v ^ c1) - c1;
x = (f ^ mask1) - mask1;
y = (u ^ mask1) - mask1;
z = (v ^ mask1) - mask1;
/* Conditionally add x,y,z to g,q,r. */
g += x & c2;
q += y & c2;
r += z & c2;
/* In what follows, c1 is a condition mask for (zeta < 0) and (g & 1). */
c1 &= c2;
g += x & mask2;
q += y & mask2;
r += z & mask2;
/* In what follows, mask1 is a condition mask for (zeta < 0) and (g & 1). */
mask1 &= mask2;
/* Conditionally change zeta into -zeta-2 or zeta-1. */
zeta = (zeta ^ c1) - 1;
zeta = (zeta ^ mask1) - 1;
/* Conditionally add g,q,r to f,u,v. */
f += g & c1;
u += q & c1;
v += r & c1;
f += g & mask1;
u += q & mask1;
v += r & mask1;
/* Shifts */
g >>= 1;
u <<= 1;

View File

@@ -88,7 +88,7 @@ static int secp256k1_modinv64_det_check_pow2(const secp256k1_modinv64_trans2x2 *
static void secp256k1_modinv64_normalize_62(secp256k1_modinv64_signed62 *r, int64_t sign, const secp256k1_modinv64_modinfo *modinfo) {
const int64_t M62 = (int64_t)(UINT64_MAX >> 2);
int64_t r0 = r->v[0], r1 = r->v[1], r2 = r->v[2], r3 = r->v[3], r4 = r->v[4];
int64_t cond_add, cond_negate;
volatile int64_t cond_add, cond_negate;
#ifdef VERIFY
/* Verify that all limbs are in range (-2^62,2^62). */
@@ -175,7 +175,8 @@ static int64_t secp256k1_modinv64_divsteps_59(int64_t zeta, uint64_t f0, uint64_
* being inside [-2^63,2^63) means that casting to signed works correctly.
*/
uint64_t u = 8, v = 0, q = 0, r = 8;
uint64_t c1, c2, f = f0, g = g0, x, y, z;
volatile uint64_t c1, c2;
uint64_t mask1, mask2, f = f0, g = g0, x, y, z;
int i;
for (i = 3; i < 62; ++i) {
@@ -184,23 +185,25 @@ static int64_t secp256k1_modinv64_divsteps_59(int64_t zeta, uint64_t f0, uint64_
VERIFY_CHECK((q * f0 + r * g0) == g << i);
/* Compute conditional masks for (zeta < 0) and for (g & 1). */
c1 = zeta >> 63;
c2 = -(g & 1);
mask1 = c1;
c2 = g & 1;
mask2 = -c2;
/* Compute x,y,z, conditionally negated versions of f,u,v. */
x = (f ^ c1) - c1;
y = (u ^ c1) - c1;
z = (v ^ c1) - c1;
x = (f ^ mask1) - mask1;
y = (u ^ mask1) - mask1;
z = (v ^ mask1) - mask1;
/* Conditionally add x,y,z to g,q,r. */
g += x & c2;
q += y & c2;
r += z & c2;
g += x & mask2;
q += y & mask2;
r += z & mask2;
/* In what follows, c1 is a condition mask for (zeta < 0) and (g & 1). */
c1 &= c2;
mask1 &= mask2;
/* Conditionally change zeta into -zeta-2 or zeta-1. */
zeta = (zeta ^ c1) - 1;
zeta = (zeta ^ mask1) - 1;
/* Conditionally add g,q,r to f,u,v. */
f += g & c1;
u += q & c1;
v += r & c1;
f += g & mask1;
u += q & mask1;
v += r & mask1;
/* Shifts */
g >>= 1;
u <<= 1;

View File

@@ -50,7 +50,7 @@ int secp256k1_ecdh(const secp256k1_context* ctx, unsigned char *output, const se
overflow |= secp256k1_scalar_is_zero(&s);
secp256k1_scalar_cmov(&s, &secp256k1_scalar_one, overflow);
secp256k1_ecmult_const(&res, &pt, &s, 256);
secp256k1_ecmult_const(&res, &pt, &s);
secp256k1_ge_set_gej(&pt, &res);
/* Compute a hash of the point */

View File

@@ -9,6 +9,7 @@
#include "../../../include/secp256k1.h"
#include "../../../include/secp256k1_extrakeys.h"
#include "../../util.h"
static SECP256K1_INLINE int secp256k1_xonly_pubkey_load(const secp256k1_context* ctx, secp256k1_ge *ge, const secp256k1_xonly_pubkey *pubkey) {
return secp256k1_pubkey_load(ctx, ge, (const secp256k1_pubkey *) pubkey);
@@ -27,7 +28,7 @@ int secp256k1_xonly_pubkey_parse(const secp256k1_context* ctx, secp256k1_xonly_p
memset(pubkey, 0, sizeof(*pubkey));
ARG_CHECK(input32 != NULL);
if (!secp256k1_fe_set_b32(&x, input32)) {
if (!secp256k1_fe_set_b32_limit(&x, input32)) {
return 0;
}
if (!secp256k1_ge_set_xo_var(&pk, &x, 0)) {

View File

@@ -47,7 +47,7 @@ static void test_exhaustive_extrakeys(const secp256k1_context *ctx, const secp25
CHECK(secp256k1_memcmp_var(xonly_pubkey_bytes[i - 1], buf, 32) == 0);
/* Compare the xonly_pubkey bytes against the precomputed group. */
secp256k1_fe_set_b32(&fe, xonly_pubkey_bytes[i - 1]);
secp256k1_fe_set_b32_mod(&fe, xonly_pubkey_bytes[i - 1]);
CHECK(secp256k1_fe_equal_var(&fe, &group[i].x));
/* Check the parity against the precomputed group. */

View File

@@ -98,7 +98,7 @@ static int secp256k1_ecdsa_sig_recover(const secp256k1_scalar *sigr, const secp2
}
secp256k1_scalar_get_b32(brx, sigr);
r = secp256k1_fe_set_b32(&fx, brx);
r = secp256k1_fe_set_b32_limit(&fx, brx);
(void)r;
VERIFY_CHECK(r); /* brx comes from a scalar, so is less than the order; certainly less than p */
if (recid & 2) {

View File

@@ -232,7 +232,7 @@ int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const unsigned cha
ARG_CHECK(msg != NULL || msglen == 0);
ARG_CHECK(pubkey != NULL);
if (!secp256k1_fe_set_b32(&rx, &sig64[0])) {
if (!secp256k1_fe_set_b32_limit(&rx, &sig64[0])) {
return 0;
}

View File

@@ -215,28 +215,36 @@ static void test_schnorrsig_sha256_tagged(void) {
/* Helper function for schnorrsig_bip_vectors
* Signs the message and checks that it's the same as expected_sig. */
static void test_schnorrsig_bip_vectors_check_signing(const unsigned char *sk, const unsigned char *pk_serialized, const unsigned char *aux_rand, const unsigned char *msg32, const unsigned char *expected_sig) {
static void test_schnorrsig_bip_vectors_check_signing(const unsigned char *sk, const unsigned char *pk_serialized, const unsigned char *aux_rand, const unsigned char *msg, size_t msglen, const unsigned char *expected_sig) {
unsigned char sig[64];
secp256k1_keypair keypair;
secp256k1_xonly_pubkey pk, pk_expected;
secp256k1_schnorrsig_extraparams extraparams = SECP256K1_SCHNORRSIG_EXTRAPARAMS_INIT;
extraparams.ndata = (unsigned char*)aux_rand;
CHECK(secp256k1_keypair_create(CTX, &keypair, sk));
CHECK(secp256k1_schnorrsig_sign32(CTX, sig, msg32, &keypair, aux_rand));
CHECK(secp256k1_schnorrsig_sign_custom(CTX, sig, msg, msglen, &keypair, &extraparams));
CHECK(secp256k1_memcmp_var(sig, expected_sig, 64) == 0);
if (msglen == 32) {
memset(sig, 0, 64);
CHECK(secp256k1_schnorrsig_sign32(CTX, sig, msg, &keypair, aux_rand));
CHECK(secp256k1_memcmp_var(sig, expected_sig, 64) == 0);
}
CHECK(secp256k1_xonly_pubkey_parse(CTX, &pk_expected, pk_serialized));
CHECK(secp256k1_keypair_xonly_pub(CTX, &pk, NULL, &keypair));
CHECK(secp256k1_memcmp_var(&pk, &pk_expected, sizeof(pk)) == 0);
CHECK(secp256k1_schnorrsig_verify(CTX, sig, msg32, 32, &pk));
CHECK(secp256k1_schnorrsig_verify(CTX, sig, msg, msglen, &pk));
}
/* Helper function for schnorrsig_bip_vectors
* Checks that both verify and verify_batch (TODO) return the same value as expected. */
static void test_schnorrsig_bip_vectors_check_verify(const unsigned char *pk_serialized, const unsigned char *msg32, const unsigned char *sig, int expected) {
static void test_schnorrsig_bip_vectors_check_verify(const unsigned char *pk_serialized, const unsigned char *msg, size_t msglen, const unsigned char *sig, int expected) {
secp256k1_xonly_pubkey pk;
CHECK(secp256k1_xonly_pubkey_parse(CTX, &pk, pk_serialized));
CHECK(expected == secp256k1_schnorrsig_verify(CTX, sig, msg32, 32, &pk));
CHECK(expected == secp256k1_schnorrsig_verify(CTX, sig, msg, msglen, &pk));
}
/* Test vectors according to BIP-340 ("Schnorr Signatures for secp256k1"). See
@@ -256,7 +264,7 @@ static void test_schnorrsig_bip_vectors(void) {
0xB5, 0x31, 0xC8, 0x45, 0x83, 0x6F, 0x99, 0xB0,
0x86, 0x01, 0xF1, 0x13, 0xBC, 0xE0, 0x36, 0xF9
};
unsigned char aux_rand[32] = {
const unsigned char aux_rand[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,
@@ -278,8 +286,8 @@ static void test_schnorrsig_bip_vectors(void) {
0xEB, 0xEE, 0xE8, 0xFD, 0xB2, 0x17, 0x2F, 0x47,
0x7D, 0xF4, 0x90, 0x0D, 0x31, 0x05, 0x36, 0xC0
};
test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sig);
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 1);
test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sizeof(msg), sig);
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 1);
}
{
/* Test vector 1 */
@@ -295,7 +303,7 @@ static void test_schnorrsig_bip_vectors(void) {
0x58, 0xFE, 0xAE, 0x1D, 0xA2, 0xDE, 0xCE, 0xD8,
0x43, 0x24, 0x0F, 0x7B, 0x50, 0x2B, 0xA6, 0x59
};
unsigned char aux_rand[32] = {
const unsigned char aux_rand[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,
@@ -317,8 +325,8 @@ static void test_schnorrsig_bip_vectors(void) {
0x89, 0x7E, 0xFC, 0xB6, 0x39, 0xEA, 0x87, 0x1C,
0xFA, 0x95, 0xF6, 0xDE, 0x33, 0x9E, 0x4B, 0x0A
};
test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sig);
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 1);
test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sizeof(msg), sig);
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 1);
}
{
/* Test vector 2 */
@@ -334,7 +342,7 @@ static void test_schnorrsig_bip_vectors(void) {
0x01, 0x39, 0x71, 0x53, 0x09, 0xB0, 0x86, 0xC9,
0x60, 0xE1, 0x8F, 0xD9, 0x69, 0x77, 0x4E, 0xB8
};
unsigned char aux_rand[32] = {
const unsigned char aux_rand[32] = {
0xC8, 0x7A, 0xA5, 0x38, 0x24, 0xB4, 0xD7, 0xAE,
0x2E, 0xB0, 0x35, 0xA2, 0xB5, 0xBB, 0xBC, 0xCC,
0x08, 0x0E, 0x76, 0xCD, 0xC6, 0xD1, 0x69, 0x2C,
@@ -356,8 +364,8 @@ static void test_schnorrsig_bip_vectors(void) {
0x7A, 0xDE, 0xA9, 0x8D, 0x82, 0xF8, 0x48, 0x1E,
0x0E, 0x1E, 0x03, 0x67, 0x4A, 0x6F, 0x3F, 0xB7
};
test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sig);
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 1);
test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sizeof(msg), sig);
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 1);
}
{
/* Test vector 3 */
@@ -373,7 +381,7 @@ static void test_schnorrsig_bip_vectors(void) {
0x3A, 0x0D, 0x95, 0xFB, 0xF2, 0x1D, 0x46, 0x8A,
0x1B, 0x33, 0xF8, 0xC1, 0x60, 0xD8, 0xF5, 0x17
};
unsigned char aux_rand[32] = {
const unsigned char aux_rand[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,
@@ -395,8 +403,8 @@ static void test_schnorrsig_bip_vectors(void) {
0xF2, 0x5F, 0xD7, 0x88, 0x81, 0xEB, 0xB3, 0x27,
0x71, 0xFC, 0x59, 0x22, 0xEF, 0xC6, 0x6E, 0xA3
};
test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sig);
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 1);
test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sizeof(msg), sig);
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 1);
}
{
/* Test vector 4 */
@@ -422,7 +430,7 @@ static void test_schnorrsig_bip_vectors(void) {
0x60, 0xCB, 0x71, 0xC0, 0x4E, 0x80, 0xF5, 0x93,
0x06, 0x0B, 0x07, 0xD2, 0x83, 0x08, 0xD7, 0xF4
};
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 1);
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 1);
}
{
/* Test vector 5 */
@@ -460,7 +468,7 @@ static void test_schnorrsig_bip_vectors(void) {
0x7A, 0x73, 0xC6, 0x43, 0xE1, 0x66, 0xBE, 0x5E,
0xBE, 0xAF, 0xA3, 0x4B, 0x1A, 0xC5, 0x53, 0xE2
};
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0);
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 0);
}
{
/* Test vector 7 */
@@ -486,7 +494,7 @@ static void test_schnorrsig_bip_vectors(void) {
0x62, 0x2A, 0x95, 0x4C, 0xFE, 0x54, 0x57, 0x35,
0xAA, 0xEA, 0x51, 0x34, 0xFC, 0xCD, 0xB2, 0xBD
};
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0);
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 0);
}
{
/* Test vector 8 */
@@ -512,7 +520,7 @@ static void test_schnorrsig_bip_vectors(void) {
0xE8, 0xD7, 0xC9, 0x3E, 0x00, 0xC5, 0xED, 0x0C,
0x18, 0x34, 0xFF, 0x0D, 0x0C, 0x2E, 0x6D, 0xA6
};
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0);
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 0);
}
{
/* Test vector 9 */
@@ -538,7 +546,7 @@ static void test_schnorrsig_bip_vectors(void) {
0x4F, 0xB7, 0x34, 0x76, 0xF0, 0xD5, 0x94, 0xDC,
0xB6, 0x5C, 0x64, 0x25, 0xBD, 0x18, 0x60, 0x51
};
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0);
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 0);
}
{
/* Test vector 10 */
@@ -564,7 +572,7 @@ static void test_schnorrsig_bip_vectors(void) {
0xDB, 0xA8, 0x7F, 0x11, 0xAC, 0x67, 0x54, 0xF9,
0x37, 0x80, 0xD5, 0xA1, 0x83, 0x7C, 0xF1, 0x97
};
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0);
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 0);
}
{
/* Test vector 11 */
@@ -590,7 +598,7 @@ static void test_schnorrsig_bip_vectors(void) {
0xD1, 0xD7, 0x13, 0xA8, 0xAE, 0x82, 0xB3, 0x2F,
0xA7, 0x9D, 0x5F, 0x7F, 0xC4, 0x07, 0xD3, 0x9B
};
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0);
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 0);
}
{
/* Test vector 12 */
@@ -616,7 +624,7 @@ static void test_schnorrsig_bip_vectors(void) {
0xD1, 0xD7, 0x13, 0xA8, 0xAE, 0x82, 0xB3, 0x2F,
0xA7, 0x9D, 0x5F, 0x7F, 0xC4, 0x07, 0xD3, 0x9B
};
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0);
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 0);
}
{
/* Test vector 13 */
@@ -642,7 +650,7 @@ static void test_schnorrsig_bip_vectors(void) {
0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41
};
test_schnorrsig_bip_vectors_check_verify(pk, msg, sig, 0);
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 0);
}
{
/* Test vector 14 */
@@ -656,6 +664,147 @@ static void test_schnorrsig_bip_vectors(void) {
/* No need to check the signature of the test vector as parsing the pubkey already fails */
CHECK(!secp256k1_xonly_pubkey_parse(CTX, &pk_parsed, pk));
}
{
/* Test vector 15 */
const unsigned char sk[32] = {
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
};
const unsigned char pk[32] = {
0x77, 0x8C, 0xAA, 0x53, 0xB4, 0x39, 0x3A, 0xC4,
0x67, 0x77, 0x4D, 0x09, 0x49, 0x7A, 0x87, 0x22,
0x4B, 0xF9, 0xFA, 0xB6, 0xF6, 0xE6, 0x8B, 0x23,
0x08, 0x64, 0x97, 0x32, 0x4D, 0x6F, 0xD1, 0x17,
};
const unsigned char aux_rand[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, 0x00,
};
/* const unsigned char msg[0] = {}; */
const unsigned char sig[64] = {
0x71, 0x53, 0x5D, 0xB1, 0x65, 0xEC, 0xD9, 0xFB,
0xBC, 0x04, 0x6E, 0x5F, 0xFA, 0xEA, 0x61, 0x18,
0x6B, 0xB6, 0xAD, 0x43, 0x67, 0x32, 0xFC, 0xCC,
0x25, 0x29, 0x1A, 0x55, 0x89, 0x54, 0x64, 0xCF,
0x60, 0x69, 0xCE, 0x26, 0xBF, 0x03, 0x46, 0x62,
0x28, 0xF1, 0x9A, 0x3A, 0x62, 0xDB, 0x8A, 0x64,
0x9F, 0x2D, 0x56, 0x0F, 0xAC, 0x65, 0x28, 0x27,
0xD1, 0xAF, 0x05, 0x74, 0xE4, 0x27, 0xAB, 0x63,
};
test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, NULL, 0, sig);
test_schnorrsig_bip_vectors_check_verify(pk, NULL, 0, sig, 1);
}
{
/* Test vector 16 */
const unsigned char sk[32] = {
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
};
const unsigned char pk[32] = {
0x77, 0x8C, 0xAA, 0x53, 0xB4, 0x39, 0x3A, 0xC4,
0x67, 0x77, 0x4D, 0x09, 0x49, 0x7A, 0x87, 0x22,
0x4B, 0xF9, 0xFA, 0xB6, 0xF6, 0xE6, 0x8B, 0x23,
0x08, 0x64, 0x97, 0x32, 0x4D, 0x6F, 0xD1, 0x17,
};
const unsigned char aux_rand[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, 0x00,
};
const unsigned char msg[] = { 0x11 };
const unsigned char sig[64] = {
0x08, 0xA2, 0x0A, 0x0A, 0xFE, 0xF6, 0x41, 0x24,
0x64, 0x92, 0x32, 0xE0, 0x69, 0x3C, 0x58, 0x3A,
0xB1, 0xB9, 0x93, 0x4A, 0xE6, 0x3B, 0x4C, 0x35,
0x11, 0xF3, 0xAE, 0x11, 0x34, 0xC6, 0xA3, 0x03,
0xEA, 0x31, 0x73, 0xBF, 0xEA, 0x66, 0x83, 0xBD,
0x10, 0x1F, 0xA5, 0xAA, 0x5D, 0xBC, 0x19, 0x96,
0xFE, 0x7C, 0xAC, 0xFC, 0x5A, 0x57, 0x7D, 0x33,
0xEC, 0x14, 0x56, 0x4C, 0xEC, 0x2B, 0xAC, 0xBF,
};
test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sizeof(msg), sig);
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 1);
}
{
/* Test vector 17 */
const unsigned char sk[32] = {
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
};
const unsigned char pk[32] = {
0x77, 0x8C, 0xAA, 0x53, 0xB4, 0x39, 0x3A, 0xC4,
0x67, 0x77, 0x4D, 0x09, 0x49, 0x7A, 0x87, 0x22,
0x4B, 0xF9, 0xFA, 0xB6, 0xF6, 0xE6, 0x8B, 0x23,
0x08, 0x64, 0x97, 0x32, 0x4D, 0x6F, 0xD1, 0x17,
};
const unsigned char aux_rand[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, 0x00,
};
const unsigned char msg[] = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10,
0x11,
};
const unsigned char sig[64] = {
0x51, 0x30, 0xF3, 0x9A, 0x40, 0x59, 0xB4, 0x3B,
0xC7, 0xCA, 0xC0, 0x9A, 0x19, 0xEC, 0xE5, 0x2B,
0x5D, 0x86, 0x99, 0xD1, 0xA7, 0x1E, 0x3C, 0x52,
0xDA, 0x9A, 0xFD, 0xB6, 0xB5, 0x0A, 0xC3, 0x70,
0xC4, 0xA4, 0x82, 0xB7, 0x7B, 0xF9, 0x60, 0xF8,
0x68, 0x15, 0x40, 0xE2, 0x5B, 0x67, 0x71, 0xEC,
0xE1, 0xE5, 0xA3, 0x7F, 0xD8, 0x0E, 0x5A, 0x51,
0x89, 0x7C, 0x55, 0x66, 0xA9, 0x7E, 0xA5, 0xA5,
};
test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sizeof(msg), sig);
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 1);
}
{
/* Test vector 18 */
const unsigned char sk[32] = {
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40,
};
const unsigned char pk[32] = {
0x77, 0x8C, 0xAA, 0x53, 0xB4, 0x39, 0x3A, 0xC4,
0x67, 0x77, 0x4D, 0x09, 0x49, 0x7A, 0x87, 0x22,
0x4B, 0xF9, 0xFA, 0xB6, 0xF6, 0xE6, 0x8B, 0x23,
0x08, 0x64, 0x97, 0x32, 0x4D, 0x6F, 0xD1, 0x17,
};
const unsigned char aux_rand[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, 0x00,
};
const unsigned char sig[64] = {
0x40, 0x3B, 0x12, 0xB0, 0xD8, 0x55, 0x5A, 0x34,
0x41, 0x75, 0xEA, 0x7E, 0xC7, 0x46, 0x56, 0x63,
0x03, 0x32, 0x1E, 0x5D, 0xBF, 0xA8, 0xBE, 0x6F,
0x09, 0x16, 0x35, 0x16, 0x3E, 0xCA, 0x79, 0xA8,
0x58, 0x5E, 0xD3, 0xE3, 0x17, 0x08, 0x07, 0xE7,
0xC0, 0x3B, 0x72, 0x0F, 0xC5, 0x4C, 0x7B, 0x23,
0x89, 0x7F, 0xCB, 0xA0, 0xE9, 0xD0, 0xB4, 0xA0,
0x68, 0x94, 0xCF, 0xD2, 0x49, 0xF2, 0x23, 0x67,
};
unsigned char msg[100];
memset(msg, 0x99, sizeof(msg));
test_schnorrsig_bip_vectors_check_signing(sk, pk, aux_rand, msg, sizeof(msg), sig);
test_schnorrsig_bip_vectors_check_verify(pk, msg, sizeof(msg), sig, 1);
}
}
/* Nonce function that returns constant 0 */

View File

@@ -10,6 +10,7 @@
#include "checkmem.h"
#include "int128.h"
#include "modinv64_impl.h"
#include "util.h"
/* Limbs of the secp256k1 order. */
#define SECP256K1_N_0 ((uint64_t)0xBFD25E8CD0364141ULL)
@@ -110,8 +111,9 @@ static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a,
static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) {
secp256k1_uint128 t;
volatile int vflag = flag;
VERIFY_CHECK(bit < 256);
bit += ((uint32_t) flag - 1) & 0x100; /* forcing (bit >> 6) > 3 makes this a noop */
bit += ((uint32_t) vflag - 1) & 0x100; /* forcing (bit >> 6) > 3 makes this a noop */
secp256k1_u128_from_u64(&t, r->d[0]);
secp256k1_u128_accum_u64(&t, ((uint64_t)((bit >> 6) == 0)) << (bit & 0x3F));
r->d[0] = secp256k1_u128_to_u64(&t); secp256k1_u128_rshift(&t, 64);
@@ -188,7 +190,8 @@ static int secp256k1_scalar_is_high(const secp256k1_scalar *a) {
static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
/* If we are flag = 0, mask = 00...00 and this is a no-op;
* if we are flag = 1, mask = 11...11 and this is identical to secp256k1_scalar_negate */
uint64_t mask = !flag - 1;
volatile int vflag = flag;
uint64_t mask = -vflag;
uint64_t nonzero = (secp256k1_scalar_is_zero(r) != 0) - 1;
secp256k1_uint128 t;
secp256k1_u128_from_u64(&t, r->d[0] ^ mask);
@@ -380,7 +383,7 @@ static void secp256k1_scalar_reduce_512(secp256k1_scalar *r, const uint64_t *l)
"movq %%r10, %q5\n"
/* extract m6 */
"movq %%r8, %q6\n"
: "=g"(m0), "=g"(m1), "=g"(m2), "=g"(m3), "=g"(m4), "=g"(m5), "=g"(m6)
: "=&g"(m0), "=&g"(m1), "=&g"(m2), "=g"(m3), "=g"(m4), "=g"(m5), "=g"(m6)
: "S"(l), "i"(SECP256K1_N_C_0), "i"(SECP256K1_N_C_1)
: "rax", "rdx", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "cc");

View File

@@ -9,6 +9,7 @@
#include "checkmem.h"
#include "modinv32_impl.h"
#include "util.h"
/* Limbs of the secp256k1 order. */
#define SECP256K1_N_0 ((uint32_t)0xD0364141UL)
@@ -141,8 +142,9 @@ static int secp256k1_scalar_add(secp256k1_scalar *r, const secp256k1_scalar *a,
static void secp256k1_scalar_cadd_bit(secp256k1_scalar *r, unsigned int bit, int flag) {
uint64_t t;
volatile int vflag = flag;
VERIFY_CHECK(bit < 256);
bit += ((uint32_t) flag - 1) & 0x100; /* forcing (bit >> 5) > 7 makes this a noop */
bit += ((uint32_t) vflag - 1) & 0x100; /* forcing (bit >> 5) > 7 makes this a noop */
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));
@@ -241,7 +243,8 @@ static int secp256k1_scalar_is_high(const secp256k1_scalar *a) {
static int secp256k1_scalar_cond_negate(secp256k1_scalar *r, int flag) {
/* If we are flag = 0, mask = 00...00 and this is a no-op;
* if we are flag = 1, mask = 11...11 and this is identical to secp256k1_scalar_negate */
uint32_t mask = !flag - 1;
volatile int vflag = flag;
uint32_t mask = -vflag;
uint32_t nonzero = 0xFFFFFFFFUL * (secp256k1_scalar_is_zero(r) == 0);
uint64_t t = (uint64_t)(r->d[0] ^ mask) + ((SECP256K1_N_0 + 1) & mask);
r->d[0] = t & nonzero; t >>= 32;

View File

@@ -9,6 +9,7 @@
#include "checkmem.h"
#include "scalar.h"
#include "util.h"
#include <string.h>

View File

@@ -247,8 +247,8 @@ static int secp256k1_pubkey_load(const secp256k1_context* ctx, secp256k1_ge* ge,
} else {
/* Otherwise, fall back to 32-byte big endian for X and Y. */
secp256k1_fe x, y;
secp256k1_fe_set_b32(&x, pubkey->data);
secp256k1_fe_set_b32(&y, pubkey->data + 32);
secp256k1_fe_set_b32_mod(&x, pubkey->data);
secp256k1_fe_set_b32_mod(&y, pubkey->data + 32);
secp256k1_ge_set_xy(ge, &x, &y);
}
ARG_CHECK(!secp256k1_fe_is_zero(&ge->x));

View File

@@ -7,6 +7,8 @@
#ifndef SECP256K1_TESTRAND_H
#define SECP256K1_TESTRAND_H
#include "util.h"
/* A non-cryptographic RNG used only for test infrastructure. */
/** Seed the pseudorandom number generator for testing. */

View File

@@ -13,6 +13,7 @@
#include "testrand.h"
#include "hash.h"
#include "util.h"
static uint64_t secp256k1_test_state[4];
static uint64_t secp256k1_test_rng_integer;

View File

@@ -10,7 +10,12 @@
#include <time.h>
#ifdef USE_EXTERNAL_DEFAULT_CALLBACKS
#pragma message("Ignoring USE_EXTERNAL_CALLBACKS in tests.")
#undef USE_EXTERNAL_DEFAULT_CALLBACKS
#endif
#include "secp256k1.c"
#include "../include/secp256k1.h"
#include "../include/secp256k1_preallocated.h"
#include "testrand_impl.h"
@@ -85,7 +90,7 @@ static void random_field_element_test(secp256k1_fe *fe) {
do {
unsigned char b32[32];
secp256k1_testrand256_test(b32);
if (secp256k1_fe_set_b32(fe, b32)) {
if (secp256k1_fe_set_b32_limit(fe, b32)) {
break;
}
} while(1);
@@ -2221,7 +2226,7 @@ static void scalar_test(void) {
for (i = 0; i < 100; ++i) {
int low;
int shift = 1 + secp256k1_testrand_int(15);
int expected = r.d[0] % (1 << shift);
int expected = r.d[0] % (1ULL << shift);
low = secp256k1_scalar_shr_int(&r, shift);
CHECK(expected == low);
}
@@ -2952,7 +2957,7 @@ static void random_fe(secp256k1_fe *x) {
unsigned char bin[32];
do {
secp256k1_testrand256(bin);
if (secp256k1_fe_set_b32(x, bin)) {
if (secp256k1_fe_set_b32_limit(x, bin)) {
return;
}
} while(1);
@@ -2962,7 +2967,7 @@ static void random_fe_test(secp256k1_fe *x) {
unsigned char bin[32];
do {
secp256k1_testrand256_test(bin);
if (secp256k1_fe_set_b32(x, bin)) {
if (secp256k1_fe_set_b32_limit(x, bin)) {
return;
}
} while(1);
@@ -3016,7 +3021,7 @@ static void run_field_convert(void) {
unsigned char b322[32];
secp256k1_fe_storage fes2;
/* Check conversions to fe. */
CHECK(secp256k1_fe_set_b32(&fe2, b32));
CHECK(secp256k1_fe_set_b32_limit(&fe2, b32));
CHECK(secp256k1_fe_equal_var(&fe, &fe2));
secp256k1_fe_from_storage(&fe2, &fes);
CHECK(secp256k1_fe_equal_var(&fe, &fe2));
@@ -3027,6 +3032,72 @@ static void run_field_convert(void) {
CHECK(secp256k1_memcmp_var(&fes2, &fes, sizeof(fes)) == 0);
}
static void run_field_be32_overflow(void) {
{
static const unsigned char zero_overflow[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,
};
static const unsigned char zero[32] = { 0x00 };
unsigned char out[32];
secp256k1_fe fe;
CHECK(secp256k1_fe_set_b32_limit(&fe, zero_overflow) == 0);
secp256k1_fe_set_b32_mod(&fe, zero_overflow);
CHECK(secp256k1_fe_normalizes_to_zero(&fe) == 1);
secp256k1_fe_normalize(&fe);
CHECK(secp256k1_fe_is_zero(&fe) == 1);
secp256k1_fe_get_b32(out, &fe);
CHECK(secp256k1_memcmp_var(out, zero, 32) == 0);
}
{
static const unsigned char one_overflow[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, 0x30,
};
static const unsigned char one[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, 0x01,
};
unsigned char out[32];
secp256k1_fe fe;
CHECK(secp256k1_fe_set_b32_limit(&fe, one_overflow) == 0);
secp256k1_fe_set_b32_mod(&fe, one_overflow);
secp256k1_fe_normalize(&fe);
CHECK(secp256k1_fe_cmp_var(&fe, &secp256k1_fe_one) == 0);
secp256k1_fe_get_b32(out, &fe);
CHECK(secp256k1_memcmp_var(out, one, 32) == 0);
}
{
static const unsigned char ff_overflow[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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
};
static const unsigned char ff[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, 0x01, 0x00, 0x00, 0x03, 0xD0,
};
unsigned char out[32];
secp256k1_fe fe;
const secp256k1_fe fe_ff = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0x01, 0x000003d0);
CHECK(secp256k1_fe_set_b32_limit(&fe, ff_overflow) == 0);
secp256k1_fe_set_b32_mod(&fe, ff_overflow);
secp256k1_fe_normalize(&fe);
CHECK(secp256k1_fe_cmp_var(&fe, &fe_ff) == 0);
secp256k1_fe_get_b32(out, &fe);
CHECK(secp256k1_memcmp_var(out, ff, 32) == 0);
}
}
/* Returns true if two field elements have the same representation. */
static int fe_identical(const secp256k1_fe *a, const secp256k1_fe *b) {
int ret = 1;
@@ -3605,7 +3676,7 @@ static void run_inverse_tests(void)
b32[31] = i & 0xff;
b32[30] = (i >> 8) & 0xff;
secp256k1_scalar_set_b32(&x_scalar, b32, NULL);
secp256k1_fe_set_b32(&x_fe, b32);
secp256k1_fe_set_b32_mod(&x_fe, b32);
for (var = 0; var <= 1; ++var) {
test_inverse_scalar(NULL, &x_scalar, var);
test_inverse_field(NULL, &x_fe, var);
@@ -3622,7 +3693,7 @@ static void run_inverse_tests(void)
for (i = 0; i < 64 * COUNT; ++i) {
(testrand ? secp256k1_testrand256_test : secp256k1_testrand256)(b32);
secp256k1_scalar_set_b32(&x_scalar, b32, NULL);
secp256k1_fe_set_b32(&x_fe, b32);
secp256k1_fe_set_b32_mod(&x_fe, b32);
for (var = 0; var <= 1; ++var) {
test_inverse_scalar(NULL, &x_scalar, var);
test_inverse_field(NULL, &x_fe, var);
@@ -4338,9 +4409,9 @@ static void test_ecmult_target(const secp256k1_scalar* target, int mode) {
secp256k1_ecmult(&p2j, &pj, &n2, &zero);
secp256k1_ecmult(&ptj, &pj, target, &zero);
} else {
secp256k1_ecmult_const(&p1j, &p, &n1, 256);
secp256k1_ecmult_const(&p2j, &p, &n2, 256);
secp256k1_ecmult_const(&ptj, &p, target, 256);
secp256k1_ecmult_const(&p1j, &p, &n1);
secp256k1_ecmult_const(&p2j, &p, &n2);
secp256k1_ecmult_const(&ptj, &p, target);
}
/* Add them all up: n1*P + n2*P + target*P = (n1+n2+target)*P = (n1+n1-n1-n2)*P = 0. */
@@ -4403,7 +4474,7 @@ static void ecmult_const_random_mult(void) {
0xb84e4e1b, 0xfb77e21f, 0x96baae2a, 0x63dec956
);
secp256k1_gej b;
secp256k1_ecmult_const(&b, &a, &xn, 256);
secp256k1_ecmult_const(&b, &a, &xn);
CHECK(secp256k1_ge_is_valid_var(&a));
ge_equals_gej(&expected_b, &b);
@@ -4419,12 +4490,12 @@ static void ecmult_const_commutativity(void) {
random_scalar_order_test(&a);
random_scalar_order_test(&b);
secp256k1_ecmult_const(&res1, &secp256k1_ge_const_g, &a, 256);
secp256k1_ecmult_const(&res2, &secp256k1_ge_const_g, &b, 256);
secp256k1_ecmult_const(&res1, &secp256k1_ge_const_g, &a);
secp256k1_ecmult_const(&res2, &secp256k1_ge_const_g, &b);
secp256k1_ge_set_gej(&mid1, &res1);
secp256k1_ge_set_gej(&mid2, &res2);
secp256k1_ecmult_const(&res1, &mid1, &b, 256);
secp256k1_ecmult_const(&res2, &mid2, &a, 256);
secp256k1_ecmult_const(&res1, &mid1, &b);
secp256k1_ecmult_const(&res2, &mid2, &a);
secp256k1_ge_set_gej(&mid1, &res1);
secp256k1_ge_set_gej(&mid2, &res2);
ge_equals_ge(&mid1, &mid2);
@@ -4440,13 +4511,13 @@ static void ecmult_const_mult_zero_one(void) {
secp256k1_scalar_negate(&negone, &one);
random_group_element_test(&point);
secp256k1_ecmult_const(&res1, &point, &zero, 3);
secp256k1_ecmult_const(&res1, &point, &zero);
secp256k1_ge_set_gej(&res2, &res1);
CHECK(secp256k1_ge_is_infinity(&res2));
secp256k1_ecmult_const(&res1, &point, &one, 2);
secp256k1_ecmult_const(&res1, &point, &one);
secp256k1_ge_set_gej(&res2, &res1);
ge_equals_ge(&res2, &point);
secp256k1_ecmult_const(&res1, &point, &negone, 256);
secp256k1_ecmult_const(&res1, &point, &negone);
secp256k1_gej_neg(&res1, &res1);
secp256k1_ge_set_gej(&res2, &res1);
ge_equals_ge(&res2, &point);
@@ -4476,7 +4547,7 @@ static void ecmult_const_mult_xonly(void) {
n = base.x;
}
/* Perform x-only multiplication. */
res = secp256k1_ecmult_const_xonly(&resx, &n, (i & 1) ? &d : NULL, &q, 256, i & 2);
res = secp256k1_ecmult_const_xonly(&resx, &n, (i & 1) ? &d : NULL, &q, i & 2);
CHECK(res);
/* Perform normal multiplication. */
secp256k1_gej_set_ge(&basej, &base);
@@ -4498,7 +4569,7 @@ static void ecmult_const_mult_xonly(void) {
random_field_element_test(&x);
secp256k1_fe_sqr(&c, &x);
secp256k1_fe_mul(&c, &c, &x);
secp256k1_fe_add(&c, &secp256k1_fe_const_b);
secp256k1_fe_add_int(&c, SECP256K1_B);
} while (secp256k1_fe_is_square_var(&c));
/* If i is odd, n=d*x for random non-zero d. */
if (i & 1) {
@@ -4509,7 +4580,7 @@ static void ecmult_const_mult_xonly(void) {
} else {
n = x;
}
res = secp256k1_ecmult_const_xonly(&r, &n, (i & 1) ? &d : NULL, &q, 256, 0);
res = secp256k1_ecmult_const_xonly(&r, &n, (i & 1) ? &d : NULL, &q, 0);
CHECK(res == 0);
}
}
@@ -4534,7 +4605,7 @@ static void ecmult_const_chain_multiply(void) {
for (i = 0; i < 100; ++i) {
secp256k1_ge tmp;
secp256k1_ge_set_gej(&tmp, &point);
secp256k1_ecmult_const(&point, &tmp, &scalar, 256);
secp256k1_ecmult_const(&point, &tmp, &scalar);
}
secp256k1_ge_set_gej(&res, &point);
ge_equals_gej(&res, &expected_point);
@@ -5432,7 +5503,7 @@ static void test_ecmult_accumulate(secp256k1_sha256* acc, const secp256k1_scalar
secp256k1_ecmult(&rj3, &infj, &zero, x);
secp256k1_ecmult_multi_var(NULL, scratch, &rj4, x, NULL, NULL, 0);
secp256k1_ecmult_multi_var(NULL, scratch, &rj5, &zero, test_ecmult_accumulate_cb, (void*)x, 1);
secp256k1_ecmult_const(&rj6, &secp256k1_ge_const_g, x, 256);
secp256k1_ecmult_const(&rj6, &secp256k1_ge_const_g, x);
secp256k1_ge_set_gej_var(&r, &rj1);
ge_equals_gej(&r, &rj2);
ge_equals_gej(&r, &rj3);
@@ -7693,6 +7764,7 @@ int main(int argc, char **argv) {
run_field_half();
run_field_misc();
run_field_convert();
run_field_be32_overflow();
run_fe_mul();
run_sqr();
run_sqrt();

View File

@@ -13,13 +13,19 @@
#define EXHAUSTIVE_TEST_ORDER 13
#endif
#ifdef USE_EXTERNAL_DEFAULT_CALLBACKS
#pragma message("Ignoring USE_EXTERNAL_CALLBACKS in exhaustive_tests.")
#undef USE_EXTERNAL_DEFAULT_CALLBACKS
#endif
#include "secp256k1.c"
#include "../include/secp256k1.h"
#include "assumptions.h"
#include "group.h"
#include "testrand_impl.h"
#include "ecmult_compute_table_impl.h"
#include "ecmult_gen_compute_table_impl.h"
#include "util.h"
static int count = 2;
@@ -54,7 +60,7 @@ static void random_fe(secp256k1_fe *x) {
unsigned char bin[32];
do {
secp256k1_testrand256(bin);
if (secp256k1_fe_set_b32(x, bin)) {
if (secp256k1_fe_set_b32_limit(x, bin)) {
return;
}
} while(1);
@@ -192,7 +198,7 @@ static void test_exhaustive_ecmult(const secp256k1_ge *group, const secp256k1_ge
}
for (j = 0; j < EXHAUSTIVE_TEST_ORDER; j++) {
for (i = 1; i < EXHAUSTIVE_TEST_ORDER; i++) {
for (i = 0; i < EXHAUSTIVE_TEST_ORDER; i++) {
int ret;
secp256k1_gej tmp;
secp256k1_fe xn, xd, tmpf;
@@ -203,19 +209,19 @@ static void test_exhaustive_ecmult(const secp256k1_ge *group, const secp256k1_ge
secp256k1_scalar_set_int(&ng, j);
/* Test secp256k1_ecmult_const. */
secp256k1_ecmult_const(&tmp, &group[i], &ng, 256);
secp256k1_ecmult_const(&tmp, &group[i], &ng);
ge_equals_gej(&group[(i * j) % EXHAUSTIVE_TEST_ORDER], &tmp);
if (j != 0) {
if (i != 0 && j != 0) {
/* Test secp256k1_ecmult_const_xonly with all curve X coordinates, and xd=NULL. */
ret = secp256k1_ecmult_const_xonly(&tmpf, &group[i].x, NULL, &ng, 256, 0);
ret = secp256k1_ecmult_const_xonly(&tmpf, &group[i].x, NULL, &ng, 0);
CHECK(ret);
CHECK(secp256k1_fe_equal_var(&tmpf, &group[(i * j) % EXHAUSTIVE_TEST_ORDER].x));
/* Test secp256k1_ecmult_const_xonly with all curve X coordinates, with random xd. */
random_fe_non_zero(&xd);
secp256k1_fe_mul(&xn, &xd, &group[i].x);
ret = secp256k1_ecmult_const_xonly(&tmpf, &xn, &xd, &ng, 256, 0);
ret = secp256k1_ecmult_const_xonly(&tmpf, &xn, &xd, &ng, 0);
CHECK(ret);
CHECK(secp256k1_fe_equal_var(&tmpf, &group[(i * j) % EXHAUSTIVE_TEST_ORDER].x));
}

View File

@@ -7,6 +7,8 @@
#ifndef SECP256K1_UTIL_H
#define SECP256K1_UTIL_H
#include "../include/secp256k1.h"
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
@@ -17,6 +19,38 @@
#define DEBUG_CONFIG_MSG(x) "DEBUG_CONFIG: " x
#define DEBUG_CONFIG_DEF(x) DEBUG_CONFIG_MSG(#x "=" STR(x))
/* Debug helper for printing arrays of unsigned char. */
#define PRINT_BUF(buf, len) do { \
printf("%s[%lu] = ", #buf, (unsigned long)len); \
print_buf_plain(buf, len); \
} while(0)
static void print_buf_plain(const unsigned char *buf, size_t len) {
size_t i;
printf("{");
for (i = 0; i < len; i++) {
if (i % 8 == 0) {
printf("\n ");
} else {
printf(" ");
}
printf("0x%02X,", buf[i]);
}
printf("\n}\n");
}
# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
# if SECP256K1_GNUC_PREREQ(2,7)
# define SECP256K1_INLINE __inline__
# elif (defined(_MSC_VER))
# define SECP256K1_INLINE __inline
# else
# define SECP256K1_INLINE
# endif
# else
# define SECP256K1_INLINE inline
# endif
typedef struct {
void (*fn)(const char *text, void* data);
const void* data;

View File

@@ -7,8 +7,6 @@ Generate a C file with ECDSA testvectors from the Wycheproof project.
'''
import json
import hashlib
import urllib.request
import sys
filename_input = sys.argv[1]
@@ -19,7 +17,8 @@ with open(filename_input) as f:
num_groups = len(doc['testGroups'])
def to_c_array(x):
if x == "": return ""
if x == "":
return ""
s = ',0x'.join(a+b for a,b in zip(x[::2], x[1::2]))
return "0x" + s
@@ -43,18 +42,23 @@ for i in range(num_groups):
sig_size = len(test_vector['sig']) // 2
msg_size = len(test_vector['msg']) // 2
if test_vector['result'] == "invalid": expected_verify = 0
elif test_vector['result'] == "valid": expected_verify = 1
else: raise ValueError("invalid result field")
if test_vector['result'] == "invalid":
expected_verify = 0
elif test_vector['result'] == "valid":
expected_verify = 1
else:
raise ValueError("invalid result field")
if num_vectors != 0 and sig_size != 0: signatures += ",\n "
if num_vectors != 0 and sig_size != 0:
signatures += ",\n "
new_msg = False
msg = to_c_array(test_vector['msg'])
msg_offset = offset_msg_running
# check for repeated msg
if msg not in cache_msgs.keys():
if num_vectors != 0 and msg_size != 0: messages += ",\n "
if msg not in cache_msgs:
if num_vectors != 0 and msg_size != 0:
messages += ",\n "
cache_msgs[msg] = offset_msg_running
messages += msg
new_msg = True
@@ -65,8 +69,9 @@ for i in range(num_groups):
pk = to_c_array(public_key['uncompressed'])
pk_offset = offset_pk_running
# check for repeated pk
if pk not in cache_public_keys.keys():
if num_vectors != 0: public_keys += ",\n "
if pk not in cache_public_keys:
if num_vectors != 0:
public_keys += ",\n "
cache_public_keys[pk] = offset_pk_running
public_keys += pk
new_pk = True
@@ -76,15 +81,11 @@ for i in range(num_groups):
signatures += to_c_array(test_vector['sig'])
out += " /" + "* tcId: " + str(test_vector['tcId']) + ". " + test_vector['comment'] + " *" + "/\n"
out += " {" + "{0}, {1}, {2}, {3}, {4}, {5}".format(
pk_offset,
msg_offset,
msg_size,
offset_sig,
sig_size,
expected_verify) + " },\n"
if new_msg: offset_msg_running += msg_size
if new_pk: offset_pk_running += 65
out += f" {{{pk_offset}, {msg_offset}, {msg_size}, {offset_sig}, {sig_size}, {expected_verify} }},\n"
if new_msg:
offset_msg_running += msg_size
if new_pk:
offset_pk_running += 65
offset_sig += sig_size
num_vectors += 1
@@ -101,7 +102,7 @@ typedef struct {
print("/* Note: this file was autogenerated using tests_wycheproof_generate.py. Do not edit. */")
print("#define SECP256K1_ECDSA_WYCHEPROOF_NUMBER_TESTVECTORS ({})".format(num_vectors))
print(f"#define SECP256K1_ECDSA_WYCHEPROOF_NUMBER_TESTVECTORS ({num_vectors})")
print(struct_definition)