-
Notifications
You must be signed in to change notification settings - Fork 38.7k
Utils: Improvements to ECDSA key-handling code #10657
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
Conversation
src/key.cpp
Outdated
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 guess that's not possible...
src/pubkey.cpp
Outdated
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.
This change breaks the intentional compatibility with OpenSSL behavior; it also makes the commit message inaccurately described.
It doesn't matter for the Bitcoin system anymore because only strict DER matters there now, but this is otherwise an undisclosed consensus change (admittedly where OpenSSL creates inconsistency to begin with).
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.
We made this change because the previous check was platform-dependent and therefore difficult to review for determinism (and also we don't use the lax code at all, and have removed it). As far as being an undisclosed consensus change, it's obviously not one that would end up affecting running consensus (because compilation would fail on the target machines this affects), but ACK that it would have been clearer in a separate commit. I can revert it for this PR if desired.
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.
If lenbyte >= 4 here, then rlen calculated in the while loop just below will be >= 224 (because lenbyte at this point is the length of the representation of rlen after stripping leading zeros). So this function would in any case return 0 at line 90 if it does not return 0 here: the condition rlen > inputlen - pos would be true at line 90 since inputlen is at most the maximum block size, which is less than 224 bytes.
@str4d's reasoning is not quite correct; the above argument isn't obvious and doesn't hold just because of the static_assert. In any case there is no consensus change (it doesn't matter whether we return 0 here or at line 90).
If this had actually made a difference, then there would have been a consensus incompatibility between 32-bit and 64-bit platforms, which would surely have been unintended. (I know that originally only 64-bit platforms were supported, but my understanding is that the current code is supposed to support both with no consensus differences.)
Edit: correct 232 to 224. (The most significant byte, which has weight at least 224 when lenbyte >= 4, must be at least 1.)
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.
If this had actually made a difference, then there would have been a consensus incompatibility between 32-bit and 64-bit platforms, which would surely have been unintended.
It was intended to preserve exact compatibility with OpenSSL which has the same behavior. (particularly during a time when this behavior was embargoed both for us and OpenSSL)
And it very much made a different prior to BIP66, it doesn't now-- but this parsing function exists entirely for compatibility with OpenSSL and would not have been used if Bitcoin used BIP66 since day one.
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.
It didn't make any difference prior to BIP66, by the argument I gave above -- fortunately, because it would have been possible to fork 32-bit nodes from 64-bit nodes otherwise.
It is basically never correct to have a platform-dependent consensus check. In this case, platform-dependent consensus code happened not to result in a difference in behaviour, essentially by luck. IMHO it's a good idea to clean that up.
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.
@daira It is absolutely never correct to have platform-dependent consensus checks. However, Bitcoin used to indirectly have such a check through OpenSSL (fixed in CVE-2014-8275, see https://www.openssl.org/news/secadv/20150108.txt), and it was in fact possible to fork 32-bit nodes from 64-bit nodes. BIP66 was exactly intended to fix that problem (see https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-July/009697.html). The original code here just preserved the behaviour. No problem with removing the dependency now, though.
src/pubkey.cpp
Outdated
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.
same 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.
Same argument as above with rlen replaced by slen, and line 90 replaced by line 129.
src/pubkey.cpp
Outdated
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.
Help me understand how you believe there is a potential overflow here.
My meat based range analysis states: Pos always has value 2 here. Size_t lenbyte is 0-127 inclusive (after the subtraction takes it from a range of 128-255 inclusive). This means that the left side (which is all size_t) has a range of 2-129.
What am I missing? (As an aside, zcash really screwed up if there is any reason to use this lax parser in it; this code exists for compatibility with OpenSSL...)
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.
And likewise for the below.
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.
See zcash/zcash#2335 (comment):
This is a different style to before but it's still overflow-prone (for integer overflows this time).
So this change was included for consistency with the other changes, not necessarily because this specific instance suffers from overflow, but because that style of pointer comparison can be vulnerable, and it is better to have good style precedent. There's no telling what future people might happen to do with that code snippet.
(As an aside, zcash really screwed up if there is any reason to use this lax parser in it; this code exists for compatibility with OpenSSL...)
In fact, we stripped out this code as unused and unnecessary in zcash/zcash#2360, but for the purposes of upstreaming to Bitcoin Core where it was still present, we intentionally separated that change from these ones.
|
Thanks for upstreaming this! utACK d6c7ab9d27a56f08d4072a352640d55d5e46f484 |
|
Needs rebase. |
d6c7ab9 to
1ce9f0a
Compare
|
Rebased on master to fix conflict (an adjacent line being changed). |
TheBlueMatt
left a comment
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.
Looks like travis failed. I believe its unrelated, however.
| 2011, Matt Corallo <matt@bluematt.me> | ||
| License: GPL-2+ | ||
|
|
||
| Files: src/secp256k1/build-aux/m4/ax_jni_include_dir.m4 |
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.
These seem like rather unrelated changes? Can they go in a separate PR?
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.
They were related inasmuch as I was pulling in a collection of libsecp256k1 PRs from upstream, and this was a necessary libsecp256k1-related addition. From a Bitcoin PR perspective, I can split this out into a separate PR if desired.
src/pubkey.h
Outdated
| * const unsigned int SIGNATURE_SIZE = 72; | ||
| * | ||
| */ | ||
| const unsigned int PUBLIC_KEY_SIZE = 65; |
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.
yikes, please don't put these in the global namespace in a very public header file.
src/key.h
Outdated
| * const unsigned int SIGNATURE_SIZE = 72; | ||
| * | ||
| */ | ||
| const unsigned int PRIVATE_KEY_SIZE = 279; |
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.
Same namespace issue here.
|
Looks like a spurious unrelated Travis failure. |
|
Needs comments by @cfields addressed, I agree putting constants such as PUBLIC_KEY_SIZE in the global namespace seems a bad idea, they should be scoped to some class. |
|
Thanks! |
63179d0 Scope the ECDSA constant sizes to CPubKey / CKey classes (Jack Grigg) 1ce9f0a Ensure that ECDSA constant sizes are correctly-sized (Jack Grigg) 48abe78 Remove redundant `= 0` initialisations (Jack Grigg) 17fa391 Specify ECDSA constant sizes as constants (Jack Grigg) e4a1086 Update Debian copyright list (Jack Grigg) e181dbe Add comments (Jack Grigg) a3603ac Fix potential overflows in ECDSA DER parsers (Jack Grigg) Pull request description: Mostly trivial, but includes fixes to potential overflows in the ECDSA DER parsers. Cherry-picked from Zcash PR zcash/zcash#2335 Tree-SHA512: 8fcbd51b0bd6723e5d33fa5d592f7cb68ed182796a9b837ecc8217991ad69d6c970258617dc00eb378c8caa4cec5d6b304d9d2c066acd40cda98e4da68e0caa4
Scope the ECDSA constant sizes to CPubKey / CKey classes Cherry-picked from bitcoin/bitcoin#10657, upstreaming our patches from #2335.
63179d0 Scope the ECDSA constant sizes to CPubKey / CKey classes (Jack Grigg) 1ce9f0a Ensure that ECDSA constant sizes are correctly-sized (Jack Grigg) 48abe78 Remove redundant `= 0` initialisations (Jack Grigg) 17fa391 Specify ECDSA constant sizes as constants (Jack Grigg) e4a1086 Update Debian copyright list (Jack Grigg) e181dbe Add comments (Jack Grigg) a3603ac Fix potential overflows in ECDSA DER parsers (Jack Grigg) Pull request description: Mostly trivial, but includes fixes to potential overflows in the ECDSA DER parsers. Cherry-picked from Zcash PR zcash/zcash#2335 Tree-SHA512: 8fcbd51b0bd6723e5d33fa5d592f7cb68ed182796a9b837ecc8217991ad69d6c970258617dc00eb378c8caa4cec5d6b304d9d2c066acd40cda98e4da68e0caa4
63179d0 Scope the ECDSA constant sizes to CPubKey / CKey classes (Jack Grigg) 1ce9f0a Ensure that ECDSA constant sizes are correctly-sized (Jack Grigg) 48abe78 Remove redundant `= 0` initialisations (Jack Grigg) 17fa391 Specify ECDSA constant sizes as constants (Jack Grigg) e4a1086 Update Debian copyright list (Jack Grigg) e181dbe Add comments (Jack Grigg) a3603ac Fix potential overflows in ECDSA DER parsers (Jack Grigg) Pull request description: Mostly trivial, but includes fixes to potential overflows in the ECDSA DER parsers. Cherry-picked from Zcash PR zcash/zcash#2335 Tree-SHA512: 8fcbd51b0bd6723e5d33fa5d592f7cb68ed182796a9b837ecc8217991ad69d6c970258617dc00eb378c8caa4cec5d6b304d9d2c066acd40cda98e4da68e0caa4
Mostly trivial, but includes fixes to potential overflows in the ECDSA DER parsers.
Cherry-picked from Zcash PR zcash/zcash#2335