-
-
Notifications
You must be signed in to change notification settings - Fork 792
md: fix return values of EVP_DigestVerify(Final) #2449
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
Open
huwcbjones
wants to merge
3
commits into
sfackler:master
Choose a base branch
from
huwcbjones:huw/md/fix-digest-verify
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 silently ignores errors if they're on teh stack --
digest_verify_final
deliberately tried to preserve these if they existed.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.
Yeah, however you can't use these APIs to power the ECDSA sign/verify API and have the ECDSA tests pass (see huwcbjones@1108ddb).
Also, if we don't clear the error stack in the
Ok(true)
case, then the assertion that ensures the error stack is clear fails!Hence me trying to avoid changing the test code (as much as possible)!
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'm not sure I understand: if OpenSSL puts an error on the stack, we want to return that to the user, not silently ignore it.
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.
EcdsaSigRef.verify currently uses
ECDSA_do_verify
. This func is deprecated, however the return values from rust function are as follows:Ok(true)
: sig OKOk(false)
: sig invalidErr(_)
: some other error occurredThere are tests for both
Ok(true)
andOk(false)
cases.To verify an ECDSA signature in a non-deprecated way, the answer is to use
EVP_Digest*
APIs. There's already a wrapper for these APIs in md_ctx. The doc string fordigest_verify[_final]
states:rust-openssl/openssl/src/md_ctx.rs
Lines 372 to 373 in 6a87a2c
So naturally this sounds like an ideal drop-in replacement for
ECDSA_do_verify
.The docs for
EVP_DigestVerify
say that 1=sig OK, 0= sig invalid, else=some other error.However, when you get a 0 (sig invalid) rc, openssl will also (maybe) put an error on the stack saying invalid sig.
So the current implementation of
digest_verify_final
can never returnOk(false)
as documented because the error stack (at least in the RSA case) is never empty! And fordigest_verify
, it will also never returnOk(false)
becausecvt
will throw an Err at a non-1 rc, soOk(rc==1)
will always evaulate to true.The test
verify_fail
signs the string"Some Crypto Text"
with a key, then verifies the signature against"Some Crypto text"
(lower case T). From the ossl docs, we should get a return code of 0 because "the signature did not verify successfully (that is, tbs [data to be verified] did not match the original data...)".If you fix the test
The test now fails because it gets an error, even though the return code is 0. Case in-point, running the test with the following diff applied:
Gives you
This change fixes the implementation to match what's documented and as a side-effect clears the error stack in the case that the signature is invalid, because the
verify_fail
test explicits tests to make sure the error stack is clear afterdigest_verify_final
is called (regardless of the return value).Going back to how I got here, as
digest_verify_final
never returnsOk(false)
in the case where the signature is not valid for the given data, I cannot use the MdCtx sig verification functions as written to replace the deprecatedECDSA_do_verify
because the tests fail becauseOk(false)
is never returned (the existing API contract would be broken).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.
Now with that said and all the reading code I've done, there's also another implementation of the
EVP_Digest*
APIs insign.rs
that does exactly what I need and implements the return value checking fromEVP_DigestVerifyFinal
correctly (and it older than the MdCtx impl)!rust-openssl/openssl/src/sign.rs
Lines 530 to 543 in 6a87a2c
^ that's literally what I wrote in this PR without even seeing it! 🤣 🤦🏻♂️
Anyhow, I've got another way to do what I want, so I'll leave it to you whether want to take this change, or want the docs fixing.