-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
build: make libsodium an optional build dependency #9668
base: master
Are you sure you want to change the base?
Conversation
There were earlier discussions/PRs expanding the use of libsodium, for example, #4159. It's meant to be a fairly small and concise library so I'm not sure how much benefit eliminating it, versus replacing existing in-tree code with it, provides. |
NACK. We can also use |
crypto_verify_n(const unsigned char *x_, const unsigned char *y_, | ||
const int n) | ||
{ | ||
const __m128i zero = _mm_setzero_si128(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Worth noting: This very much requires strict aliasing disabled (which sodium does, quite explicitly, and by design; whereas this project's CMakeLists.txt suggest an intent to go the other direction):
# With GCC 6.1.1 the compiled binary malfunctions due to aliasing. Until that
# is fixed in the code (Issue #847), force compiler to be conservative.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-strict-aliasing")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing")
The more creative the compiler vendors get, the more problematic even a single vendored function like this becomes.
It happens that this PR crosses paths with a few other issues that bothered me recently, all to do with memory layout/alignment issues. Per the line comment I just posted, precisely because of those issues, I really dislike vendoring crypto functions. If you want to eliminate |
To further motivate why I submitted this PR and respond to some of the comments here: I think we should eliminate chain split risk as much as possible. That means that we should avoid using library functions for our consensus. Otherwise, we trust that the semantics of these functions are never changed. If there is a change, even non-malicious, or through miscompilation, it could result in a chain split (inadvertently or through an introduced exploit). This risk exists even if we don't update the library in our release builds. Many economic participants (exchanges, services, etc) run custom builds in production. These builds use library versions that don't necessarily correspond with our 'official' release builds. Library authors therefore have the power to change the consensus under which a significant number of nodes operate without our approval by simply releasing a new library version. Monero doesn't have a consensus engine library like libbitcoinkernel, so it's unclear precisely which library functions underpin our consensus. Of our build dependencies, various boost components and this one function from libsodium are certainly used: A consensus library is something I would like to move towards in the long-term, but it necessitates that we 'own' our consensus code. If we must use third-party code, then vendoring ensures that we are in control when it changes (preferably never). This way we can benefit from 'better', higher quality, audited code that can be thoroughly tested within our builds without introducing chain split risk. If implemented correctly, cryptographic functions require very little, if any, maintenance. Whereas library dependencies have an ongoing maintenance burden through package updates. Consider also that our consensus code must be maintained indefinitely and is likely to survive longer than any third-party library, thus vendoring will occur eventually. If not now, then years or decades from now. There is also a desire from downstream projects for lower build complexity. Even if I do not find support in vendoring this particular function, replacing it with The code in this PR isn't worked out (hence drafted), I was mostly looking for concept approvals - which seems unlikely now, unless what I have written here happens to strike a chord. |
There are two problems with this premise as the justification for vendoring:
I may agree with your proposal to limit dependencies:
We're not getting rid of OpenSSL any time soon. Many cryptography and server projects depend on it somehow, meaning it's not a difficult to obtain or build external library. There's an important discussion to be had about whether to ditch libsodium, or expand its usage, but I don't see a compelling case for keeping it just for a pair of functions we can replace with well-known alternatives. |
This PR is a step towards removing libsodium as a release build dependency.
We don't need to pull in libsodium for one evergreen function (
crypto_verify_32
). This PR vendors that function insrc/crypto
. Libsodium is now only required when building with Trezor support.The code was copied from:
src/libsodium/include/crypto_verify_32.h
andsrc/libsodium/crypto_verify/verify.c
in the libsodium repo checked out at1.0.20-RELEASE
, with minor (non-functional) changes.Trezor uses
crypto_aead_chacha20poly1305_ietf_decrypt
from libsodium insrc/device_trezor/protocol.cpp
which is a bit more complicated to vendor. We may want to consider using the upstream implementation or OpenSSL rather than libsodium's.