-
Notifications
You must be signed in to change notification settings - Fork 37.7k
Security enhancements to ChaCha20::SetKey and CSignatureCache::ComputeEntryECDSA #21781
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
Security enhancements to ChaCha20::SetKey and CSignatureCache::ComputeEntryECDSA #21781
Conversation
Concept ACK: preconditions should be checked where possible I take it you have started fuzzing Bitcoin Core again @guidovranken? That's very good news for Bitcoin :) Don't forget to any fuzzing trophies to https://github.com/bitcoin-core/bitcoin-devwiki/wiki/Fuzz-Trophies :) |
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.
I wonder if this is better done with a scripted-diff
@@ -53,7 +53,7 @@ class CSignatureCache | |||
ComputeEntryECDSA(uint256& entry, const uint256 &hash, const std::vector<unsigned char>& vchSig, const CPubKey& pubkey) const | |||
{ | |||
CSHA256 hasher = m_salted_hasher_ecdsa; | |||
hasher.Write(hash.begin(), 32).Write(&pubkey[0], pubkey.size()).Write(&vchSig[0], vchSig.size()).Finalize(entry.begin()); | |||
hasher.Write(hash.begin(), 32).Write(&pubkey[0], pubkey.size()).Write(vchSig.data(), vchSig.size()).Finalize(entry.begin()); |
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.
Why is this changed here, but the other 55 instances are left as is? Including the one in this line and another one in this file?
See also commit 592404f
And our developer notes:
- Watch out for out-of-bounds vector access. `&vch[vch.size()]` is illegal,
including `&vch[0]` for an empty vector. Use `vch.data()` and `vch.data() +
vch.size()` instead.
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.
Also, it could make sense to open two pull requests for the changes here, since they seem unrelated? (One of them is also failing the fuzz task, btw)
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.
Why is this changed here, but the other 55 instances are left as is? Including the one in this line and another one in this file?
I didn't change the two instances of &pubkey[0]
in this file because the CPubkey subscript operator returns a reference to a regular array instead of a vector, so no undefined behavior rules are violated.
I didn't change any other instances of &vch[0]
because this instance specifically was the only one which came up with fuzzing (so far) with -D_GLIBCXX_DEBUG
.
Also, it could make sense to open two pull requests for the changes here, since they seem unrelated?
@laanwj suggested I create two commits in 1 PR.
(One of them is also failing the fuzz task, btw)
It fails because it instantiates ChaCha20 with a key that is 17..31
bytes large whereas my change requires that it is either 16 or 32 bytes.
I can either relax the condition in ChaCha20 to allow keys 16..32
bytes large, or change the fuzzer to pick one of (16, 32)
, let me know which you prefer.
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.
I didn't change any other instances of
&vch[0]
because this instance specifically was the only one which came up with fuzzing (so far) with-D_GLIBCXX_DEBUG
.
-D_GLIBCXX_DEBUG
is great! :)
@guidovranken, you don't happen to have any notes saved on any tweaks you had to make to get a full -D_GLIBCXX_DEBUG
compile including dependencies for Bitcoin Core? IIRC our Boost dependencies were a bit cumbersome to get compiled with -D_GLIBCXX_DEBUG
at least historically.
If anyone wants to add a CI job which runs the tests (unit + functional + fuzz) under -D_GLIBCXX_DEBUG
I'd be more than happy to review such a PR.
I can either relax the condition in ChaCha20 to allow keys
16..32
bytes large, or change the fuzzer to pick one of(16, 32)
, […]
Asserting the precondition (like you've already done) and modifying the fuzzer to fulfil said precondition is probably the best option.
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.
tweaks you had to make to get a full -D_GLIBCXX_DEBUG compile including dependencies for Bitcoin Core?
IIRC our Boost dependencies were a bit cumbersome to get compiled with -D_GLIBCXX_DEBUG at least historically.
Note that depends builds with DEBUG=1
have always used -D_GLIBCXX_DEBUG
&& D_GLIBCXX_DEBUG_PEDANTIC
. If building depends with DEBUG=1
don't work for some reason, please open an issue.
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.
Thanks @guidovranken and @fanquake for suggesting both -D_GLIBCXX_DEBUG
and -D_GLIBCXX_DEBUG_PEDANTIC
Looks like there are more issues than this one. I've reported them here:
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.
Is there a downside splitting this into two pulls? I'd still prefer that to make it easier to review, because both commits can be reviewed independently. Also, it makes a cleaner history and discussion because two unrelated threads aren't intertwined.
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.
I went ahead and split the raw data pointer commit into a separate pull (#21817). I hope this is ok. The commit hash needed to be changed, but the author information is fully preserved.
If anyone wants to tackle
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
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.
ACK, but still needs the tests fixed
Concept ACK |
fac30ee refactor: Replace &foo[0] with foo.data() (MarcoFalke) faece47 refactor: Avoid &foo[0] on C-Style arrays (MarcoFalke) face961 refactor: Use only one temporary buffer in CreateObfuscateKey (MarcoFalke) fa05ddd refactor: Use CPubKey vector constructor where possible (MarcoFalke) fabb6df script: Replace address-of idiom with vector data() method (Guido Vranken) Pull request description: The main theme of this refactor is to replace `&foo[0]` with `foo.data()`. The first commit is taken from #21781 with the rationale: * In CSignatureCache::ComputeEntryECDSA, change the way a vector pointer is resolved to prevent invoking undefined behavior if the vector is empty. The other commits aim to remove all `&foo[0]`, where `foo` is any kind of byte representation. The rationale: * Sometimes alternative code without any raw data pointers is easier to read (refer to the respective commit message for details) * If the raw data pointer is needed, `foo.data()` should be preferred, as pointed out in the developer notes. This addresses the instances that have been missed in commit 592404f, and #9804 ACKs for top commit: laanwj: Code review ACK fac30ee practicalswift: cr ACK fac30ee: patch looks correct promag: Code review ACK fac30ee. Tree-SHA512: e7e73146edbc78911a8e8c728b0a1c6b0ed9a88a008e650aa5dbffe72425bd42c76df70199a9cf7e02637448d7593e0eac52fd0f91f59240283e1390ee21bfa5
🐙 This pull request conflicts with the target branch and needs rebase. Want to unsubscribe from rebase notifications on this pull request? Just convert this pull request to a "draft". |
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.
PR description should be updated: Add a check to ChaCha20::SetKey which validates the size of the specified key, and throws an exception if it is invalid asserts that the specified key size is valid.
Are there steps to reproduce the |
@guidovranken Are you still working on this? |
PR desc updated.
Should I add a test?
I've addressed the outstanding issues. Anything else? |
See #21781 (comment) |
For example. Any other way to first observe the bug and then to observe the fix is also welcome. |
How can I test if an assertion failure occurs in the tests? |
I was wondering how you've found the bug on master. Code review or some other way? |
I found the bug with Cryptofuzz, which is now running on OSS-Fuzz as part of the In Cryptofuzz, I work around the bug by not passing an invalid key size: https://github.com/guidovranken/cryptofuzz/blob/61f27a0afa28942a8bdb8de49775cb734acf0121/modules/bitcoin/module.cpp#L252-L254 I can remove that check once this PR is merged, and add no unit tests to |
There hasn't been much activity lately and the patch still needs rebase. What is the status here?
|
There hasn't been much activity lately and the patch still needs rebase. What is the status here?
|
Closing for now due to inactivity. I think a new pull can be opened if anyone picks this up. Most of the discussion is about the already merged part: #21817 |
Uh oh!
There was an error while loading. Please reload this page.