c82d84bb86 build: add CMake option for disabling symbol visibility attributes (Cory Fields)
ce7923874f build: Add SECP256K1_NO_API_VISIBILITY_ATTRIBUTES (Tim Ruffing)
e5297f6d79 build: Refactor visibility logic (Tim Ruffing)
Pull request description:
This is less invasive than #1695. The latter might be the right thing in a new library (and then we'd probably not support autotools in the first place), but any semantic change to this code has the potential to create news bug, or at least breakages for downstream users.
This is different from #1677 in that it does not set `hidden` explicitly. I agree with the comment in #1677 that setting `hidden` violates the principle of least surprise.
So this similar in spirit to #1674. So I wonder if this should also include
3eef7362c4. I'd say no, `fvisibility` should then set by the user. But can you, in CMake, set `CMAKE_C_VISIBILITY_PRESET` from a parent project?
ACKs for top commit:
hebasto:
ACK c82d84bb86, I have reviewed the code and it looks OK.
Tree-SHA512: dad36c32a108d813e8d4e1849260af43f79a9aa8fbfb9a42b07d737e0467924a511110df0a2c6761539a1587b617a1b11123610a3db9d4cdf2b985dfb3eb21da
37dd422b5c cmake: Emulate Libtool's behavior on FreeBSD (Hennadii Stepanov)
Pull request description:
Building the master branch @ f24b838bed on FreeBSD 14.3:
- with Autotools:
```
$ ./autogen.sh
$ ./configure --disable-static --prefix /tmp/AUTOTOOLS
$ gmake
$ gmake install
$ tree /tmp/AUTOTOOLS/lib
/tmp/AUTOTOOLS/lib
├── libsecp256k1.la
├── libsecp256k1.so -> libsecp256k1.so.5.0.1
├── libsecp256k1.so.5 -> libsecp256k1.so.5.0.1
├── libsecp256k1.so.5.0.1
└── pkgconfig
└── libsecp256k1.pc
2 directories, 5 files
```
- with CMake:
```
$ cmake -B build -DCMAKE_INSTALL_PREFIX=/tmp/CMAKE
$ cmake --build build
$ cmake --install build
$ tree /tmp/CMAKE/lib
/tmp/CMAKE/lib
├── cmake
│ └── libsecp256k1
│ ├── libsecp256k1-config-version.cmake
│ ├── libsecp256k1-config.cmake
│ ├── libsecp256k1-targets-relwithdebinfo.cmake
│ └── libsecp256k1-targets.cmake
├── libsecp256k1.so -> libsecp256k1.so.5
├── libsecp256k1.so.5
└── pkgconfig
└── libsecp256k1.pc
4 directories, 7 files
```
With this PR:
```
$ cmake -B build -DCMAKE_INSTALL_PREFIX=/tmp/CMAKE+PR
$ cmake --build build
$ cmake --install build
$ tree /tmp/CMAKE+PR/lib
/tmp/CMAKE+PR/lib
├── cmake
│ └── libsecp256k1
│ ├── libsecp256k1-config-version.cmake
│ ├── libsecp256k1-config.cmake
│ ├── libsecp256k1-targets-relwithdebinfo.cmake
│ └── libsecp256k1-targets.cmake
├── libsecp256k1.so -> libsecp256k1.so.5
├── libsecp256k1.so.5 -> libsecp256k1.so.5.0.1
├── libsecp256k1.so.5.0.1
└── pkgconfig
└── libsecp256k1.pc
4 directories, 8 files
```
From [FreeBSD Developers' Handbook](https://docs.freebsd.org/en/books/developers-handbook/policies/#policies-shlib):
> If you are adding shared library support to a port or other piece of software that does not have one, the version numbers should follow these rules. Generally, the resulting numbers will have nothing to do with the release version of the software.
>
> For ports:
>
> - Prefer using the number already selected by upstream
>
> - If upstream provides symbol versioning, ensure that we use their script
ACKs for top commit:
real-or-random:
utACK 37dd422b5c
Tree-SHA512: b603d7e293ae1fb15c2b3c05957dcc3cbe94294083ad1d8cb00b06b0e295597fa09719d32c18d628670952b6d00467f5bc884be9ab791baf59ec265e26032470
Parent projects (Bitcoin Core in this case) may wish to include secp256k1
in another static library (libbitcoinkernel) so that users are not forced
to bring their own static libsecp256k1.
Unfortunately, CMake lacks the machinery to link (combine) one static lib
into another.
To work around this, secp256k1_objs is exposed as an interface library which
parent projects can "link" into static libs..
Ubuntu 20.04 LTS has reached the end of standard support. There no
longer appear to be compelling reasons to maintain compatibility with
CMake 3.16.
The new suggested minimum, CMake 3.22, is shipped with Ubuntu 22.04 LTS,
which is supported until April 2027.
This change also introduces new CMake policies, from CMP0098 to CMP0128.
These function aliases have been described as DEPRECATED in the public
API docs already many years ago (see #701, commit 41fc7856), and in
addition explicit deprecation warnings are shown by the compiler at
least since the first official release 0.2.0 (see PR #1089, commit
fc94a2da), so it should be fine to just remove them by now.
Co-authored-by: Tim Ruffing <crypto@timruffing.de>
1823594761 Verify `compressed` argument in `secp256k1_eckey_pubkey_serialize` (Sebastian Falbesoner)
Pull request description:
Due to similarity to the public API function `secp256k1_ec_pubkey_serialize`, public API flags like `SECP256K1_EC_COMPRESSED` are sometimes mistakingly passed to `secp256k1_eckey_pubkey_serialize` in newly proposed code (this is currently the case for several modules in secp256k1-zkp, see https://github.com/BlockstreamResearch/secp256k1-zkp/pull/300), which is currently not detected. To avoid this in the future, a VERIFY_CHECK is added to check that the `compressed` argument is either 0 or 1.
ACKs for top commit:
real-or-random:
utACK 1823594761
stratospher:
ACK 1823594. Got tests failures when passing public API flags to `secp256k1_eckey_pubkey_serialize`.
Tree-SHA512: ca542afc87f33e436ba33dc55b285dfe3759007c446ef94503bc1044c7a0a7f7b2208ae82e2c9743fc5fa38cf386127f3fbfa02d2c242f28fab3041ee46f153b
Due to similarity to the public API function `secp256k1_ec_pubkey_serialize`,
public API flags like `SECP256K1_EC_COMPRESSED` are sometimes mistakingly
passed to newly proposed code (this is currently the case for several modules in
secp256k1-zkp, see https://github.com/BlockstreamResearch/secp256k1-zkp/pull/300).
which is currently not detected. To avoid this in the future, a VERIFY_CHECK
is added to check that the `compressed` argument is either 0 or 1.
765ef53335 Clear _gej instances after point multiplication to avoid potential leaks (Sebastian Falbesoner)
349e6ab916 Introduce separate _clear functions for hash module (Tim Ruffing)
99cc9fd6d0 Don't rely on memset to set signed integers to 0 (Tim Ruffing)
97c57f42ba Implement various _clear() functions with secp256k1_memclear() (Tim Ruffing)
9bb368d146 Use secp256k1_memclear() to clear stack memory instead of memset() (Tim Ruffing)
e3497bbf00 Separate between clearing memory and setting to zero in tests (Tim Ruffing)
d79a6ccd43 Separate secp256k1_fe_set_int( . , 0 ) from secp256k1_fe_clear() (Tim Ruffing)
1c08126222 Add secp256k1_memclear() for clearing secret data (Tim Ruffing)
e7d384488e Don't clear secrets in pippenger implementation (Tim Ruffing)
Pull request description:
This PR picks up #636 (which in turn picked up #448, so this is take number three) and is essentially a rebase on master.
Some changes to the original PR:
* the clearing function now has the `secp256k1_` prefix again, since the related helper `_memczero` got it as well (see PR #835 / commit e89278f211)
* the original commit b17a7df8145a6a86d49c354c7e7b59a432ea5346 ("Make _set_fe_int( . , 0 ) set magnitude to 0") is not needed anymore, since it was already applied in PR #943 (commit d49011f54c)
* clearing of stack memory with `secp256k1_memclear` is now also done on modules that have been newly introduced since then, i.e. schnorr and ellswift (of course, there is still no guarantee that all places where clearing is necessary are covered)
So far I haven't looked at any disassembly and possible performance implications yet (there were some concerns expressed in https://github.com/bitcoin-core/secp256k1/pull/636#issuecomment-620118629), happy to go deeper there if this gets Concept ACKed.
The proposed method of using a memory barrier to prevent optimizating away the memset is still used in BoringSSL (where it was originally picked up from) and in the Linux Kernel, see e.g. 5af122c3df/crypto/mem.c (L335) and d456068672/include/linux/string.h (L348) / d456068672/include/linux/compiler.h (L102)Fixes#185.
ACKs for top commit:
sipa:
reACK 765ef53335
real-or-random:
ACK 765ef53335
Tree-SHA512: 5a034d5ad14178c06928022459f3d4f0877d06f576b24ab07b86b3608b0b3e9273217b8309a1db606f024f3032731f13013114b1e0828964b578814d1efb2959
0f73caf7c6 test, ci: Lower default iteration count to 16 (Hennadii Stepanov)
Pull request description:
The number of test iterations in the CI remains the same.
Resolves https://github.com/bitcoin-core/secp256k1/issues/1561.
```
$ ./build/src/tests
test count = 16
random seed = 59ea2b21267ec0ef0b4d13821292489f
random run = 2936c044f82c7598a866869b9d954d42
no problems found
```
ACKs for top commit:
sipa:
utACK 0f73caf7c6
jonasnick:
ACK 0f73caf7c6
Tree-SHA512: 84b265dc5d2780b3ea0a38f50ac8871d850ef2c97f33a0a5816baf20ac71c01db8b85696b343b089d7116d9cdb9450a6ca668229d95e54a39920d0e91a3127b3
The number of test iterations in the CI remains unchanged.
Additionally, the minimum iteration counts to enable the
`test_ecmult_constants_2bit` test is adjusted from 35 to 16, so it is
run by default.
Quoting sipa (see https://github.com/bitcoin-core/secp256k1/pull/1479#discussion_r1790079414):
"When performing an EC multiplication A = aG for secret a, the resulting
_affine_ coordinates of A are presumed to not leak information about a (ECDLP),
but the same is not necessarily true for the Jacobian coordinates that come
out of our multiplication algorithm."
For the ECDH point multiplication result, the result in Jacobi coordinates should be
cleared not only to avoid leaking the scalar, but even more so as it's a representation
of the resulting shared secret.
This gives the caller more control about whether the state should
be cleaned (= should be considered secret). Moreover, it gives the
caller the possibility to clean a hash struct without finalizing it.
All of the invocations of secp256k1_memclear() operate on stack
memory and happen after the function is done with the memory object.
This commit replaces existing memset() invocations and also adds
secp256k1_memclear() to code locations where clearing was missing;
there is no guarantee that this commit covers all code locations
where clearing is necessary.
Co-Authored-By: isle2983 <isle2983@yahoo.com>
There are two uses of the secp256k1_fe_clear() function that are now separated
into these two functions in order to reflect the intent:
1) initializing the memory prior to being used -> converted to fe_set_int( . , 0 )
2) zeroing the memory after being used such that no sensitive data remains. ->
remains as fe_clear()
In the latter case, 'magnitude' and 'normalized' need to be overwritten when
VERIFY is enabled.
Co-Authored-By: isle2983 <isle2983@yahoo.com>
We rely on memset() and an __asm__ memory barrier where it's available or
on SecureZeroMemory() on Windows. The fallback implementation uses a
volatile function pointer to memset which the compiler is not clever
enough to optimize.
We should anyway prefer to use the predefined macros from <inttypes.h>.
If I haven't missed anything, this removes the last OS-specific #if,
leaving us only with compiler-specific #if(def)s.