Skip to content
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

AVM: Go19 ecdsa curve check #4917

Merged
merged 3 commits into from
Mar 1, 2023
Merged

Conversation

jannotti
Copy link
Contributor

@jannotti jannotti commented Dec 15, 2022

Go 1.19 has changed the semantics of ecdsa.Verify to panic if the public key is not on the appropriate curve. This change prepares for supporting Go 1.19 by first establishing a new rule for the AVM opcode ecdsa_verify. By doing this in a consensus upgrade while still using Go 1.17, we force the change to occur across all nodes at once, and we ensure no changes occur in evaluating old blocks.

@jannotti jannotti requested review from cce and algorandskiy December 15, 2022 19:03
@codecov
Copy link

codecov bot commented Dec 15, 2022

Codecov Report

Merging #4917 (17755d1) into master (fb95de1) will increase coverage by 0.01%.
The diff coverage is 100.00%.

@@            Coverage Diff             @@
##           master    #4917      +/-   ##
==========================================
+ Coverage   54.06%   54.07%   +0.01%     
==========================================
  Files         427      427              
  Lines       53520    53522       +2     
==========================================
+ Hits        28935    28943       +8     
+ Misses      22316    22314       -2     
+ Partials     2269     2265       -4     
Impacted Files Coverage Δ
config/consensus.go 87.69% <100.00%> (+0.03%) ⬆️
data/transactions/logic/eval.go 90.16% <100.00%> (+<0.01%) ⬆️
ledger/tracker.go 75.10% <0.00%> (-2.96%) ⬇️
ledger/testing/randomAccounts.go 56.61% <0.00%> (ø)
network/wsNetwork.go 64.92% <0.00%> (+0.17%) ⬆️
ledger/acctupdates.go 69.24% <0.00%> (+0.24%) ⬆️
catchup/service.go 70.53% <0.00%> (+0.48%) ⬆️
ledger/acctonline.go 78.81% <0.00%> (+1.03%) ⬆️
ledger/voters.go 73.13% <0.00%> (+4.47%) ⬆️

📣 We’re building smart automated test selection to slash your CI/CD build times. Learn more

@algorandskiy algorandskiy requested a review from id-ms December 15, 2022 20:55
algorandskiy
algorandskiy previously approved these changes Dec 16, 2022
@id-ms
Copy link
Contributor

id-ms commented Dec 19, 2022

Are we planning to release a new consensus go-algorand only for that?
If the answer is not, we don't really need EnablePrecheckECDSACurve. We can just add curve.IsOnCurve and after consensus takes place we are safe to upgrade to Go 1.19. (Did I understand it correctly?)

Do we suspect that there will be a valid signature the will fail on IsOnCurve?

@jannotti jannotti changed the title Go19 curve check AVM: Go19 curve check Dec 19, 2022
Copy link
Contributor

@ahangsu ahangsu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally looks right to me, I agree with Idan's idea of saving one consensus param by && secp256r1.IsOnCurve(x, y), such that we can ensure the pk to be on curve without panicing in verify.

Only one question for Idan @algoidan

Do we suspect that there will be a valid signature the will fail on IsOnCurve?

Do you mean we want to check the signature on curve? (I think signature elements should be?)

@bbroder-algo
Copy link
Contributor

looks good to me, I see you swapped the calls to SetBytes and PublicKey but they look independent also now its in the order of the argument list for Verify

@jannotti
Copy link
Contributor Author

looks good to me, I see you swapped the calls to SetBytes and PublicKey but they look independent also now its in the order of the argument list for Verify

Now that there's a potential early failure for being off curve, I figured I'd defer the work to create the big ints unless the check passes.

@jannotti jannotti marked this pull request as ready for review January 12, 2023 20:23
Curve: elliptic.P256(),
X: x,
Y: y,
if !cx.Proto.EnablePrecheckECDSACurve || secp256r1.IsOnCurve(x, y) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if !IsOnCurve() shouldn't that be an error? Or is it just result = false not verified?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's an argument for making it an error, but we did not before, and I wanted the change to be as small as possible. Do you think there are use cases that need to distinguish an error like this from failing to verify?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will think it is somewhat sus to make a different case of erroring and failing to verify... feeling like giving a larger attack surface against verifier?

https://www.reddit.com/r/cryptography/comments/qyg723/what_happens_when_a_public_key_point_does_not_lie/ Makes me recall something like verifier rejection attack (replay attack) and invalid curve attack...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this patch improves the code.

Copy link
Contributor

@bbroder-algo bbroder-algo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Returns false on verifications before performing ECDSA verification for Secp256r1 curves if x, y components of public keys are not on the curve to begin with.

Copy link
Contributor

@cce cce left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bringing back some more of the context as I recall it from when this PR was opened

Go 1.19 release notes: https://go.dev/doc/go1.19

crypto/elliptic
Operating on invalid curve points (those for which the IsOnCurve method returns false, and which are never returned by Unmarshal or by a Curve method operating on a valid point) has always been undefined behavior and can lead to key recovery attacks. If an invalid point is supplied to Marshal, MarshalCompressed, Add, Double, or ScalarMult, they will now panic.

Go issue + CL where the panic was introduced golang/go#50975

@jannotti jannotti merged commit c573d2b into algorand:master Mar 1, 2023
@cce cce changed the title AVM: Go19 curve check AVM: Go19 ecdsa curve check Mar 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants