-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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
math/big: r.Exp(x, 1, m) wrong if r is initially non-zero #22830
Comments
This is caused by an aliasing issue in This line:
will cause Later, we do compute the quotient in pieces and set for several times This does not happen when I think we can fix this by checking for |
Change https://golang.org/cl/78995 mentions this issue: |
To expand on the “no security implication” note: Thanks to @karalabe for reporting this to us first at security@golang.org. We investigated and found that this only affects (1) calls that reuse a pre-allocated receiver, and (2) the specific case Exp(x, 1, m), that is, x^1 mod m. Most crypto code uses new(big.Int).Exp(x, y, m) instead of reusing receivers. Most crypto code is also written so that a modular exponentiation with an exponent of 1 is either completely impossible or exceedingly unlikely. We examined all the uses in the standard library and believe they are unaffected, for either the first or the second reason. In x/crypto, openpgp and ssh are clearly fine (they only use new(big.Int).Exp). x/crypto/bn256 and x/crypto/otr may need closer examination. |
@rsc We've investigated |
The big question is: do applications using |
Change https://golang.org/cl/81055 mentions this issue: |
The consequences of golang/go#22830 could be serious, so out of an abundance of caution fix these up.
The consequences of golang/go#22830 could be serious, so out of an abundance of caution fix these up.
Change https://golang.org/cl/88322 mentions this issue: |
…arge In nat.divLarge (having signature (z nat).divLarge(u, uIn, v nat)), we check whether z aliases uIn or v, but aliasing is currently not checked for the u parameter. Unfortunately, z and u aliasing each other can in some cases cause errors in the computation. The q return parameter (which will hold the result's quotient), is unconditionally initialized as q = z.make(m + 1) When cap(z) ≥ m+1, z.make() will reuse z's backing array, causing q and z to share the same backing array. If then z aliases u, setting q during the quotient computation will then corrupt u, which at that point already holds computation state. To fix this, we add an alias(z, u) check at the beginning of the function, taking care of aliasing the same way we already do for uIn and v. Fixes #22830 Change-Id: I3ab81120d5af6db7772a062bb1dfc011de91f7ad Reviewed-on: https://go-review.googlesource.com/78995 Run-TryBot: Alberto Donizetti <alb.donizetti@gmail.com> Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org> Reviewed-on: https://go-review.googlesource.com/88322 Run-TryBot: Andrew Bonventre <andybons@golang.org>
Change https://golang.org/cl/89156 mentions this issue: |
…arge In nat.divLarge (having signature (z nat).divLarge(u, uIn, v nat)), we check whether z aliases uIn or v, but aliasing is currently not checked for the u parameter. Unfortunately, z and u aliasing each other can in some cases cause errors in the computation. The q return parameter (which will hold the result's quotient), is unconditionally initialized as q = z.make(m + 1) When cap(z) ≥ m+1, z.make() will reuse z's backing array, causing q and z to share the same backing array. If then z aliases u, setting q during the quotient computation will then corrupt u, which at that point already holds computation state. To fix this, we add an alias(z, u) check at the beginning of the function, taking care of aliasing the same way we already do for uIn and v. Fixes #22830 Change-Id: I3ab81120d5af6db7772a062bb1dfc011de91f7ad Reviewed-on: https://go-review.googlesource.com/78995 Run-TryBot: Alberto Donizetti <alb.donizetti@gmail.com> Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org> Reviewed-on: https://go-review.googlesource.com/89156 Run-TryBot: Andrew Bonventre <andybons@golang.org> Reviewed-by: Andrew Bonventre <andybons@golang.org>
Updates #22830 Due to not checking if the output slices alias in divLarge, calls of the form z.div(z, x, y) caused the slice z to attempt to be used to store both the quotient and the remainder of the division. CL 78995 applies an alias check to correct that error. This CL cleans up the additional div calls that attempt to supply the same slice to hold both the quotient and remainder. Note that the call in expNN was responsible for the reported error in r.Exp(x, 1, m) when r was initialized to a non-zero value. The second instance in expNNMontgomery did not result in an error due to the size of the arguments. // RR = 2**(2*_W*len(m)) mod m RR := nat(nil).setWord(1) zz := nat(nil).shl(RR, uint(2*numWords*_W)) _, RR = RR.div(RR, zz, m) Specifically, cap(RR) == 5 after setWord(1) due to const e = 4 in z.make(1) len(zz) == 2*len(m) + 1 after shifting left, numWords = len(m) Reusing the backing array for z and z2 in div was only triggered if cap(RR) >= len(zz) + 1 and len(m) > 1 so that divLarge was called. But, 5 < 2*len(m) + 2 if len(m) > 1, so new arrays were allocated and the error was never triggered in this case. Change-Id: Iedac80dbbde13216c94659e84d28f6f4be3aaf24 Reviewed-on: https://go-review.googlesource.com/81055 Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
For an exponent of
1
,big.Int.Exp
returns the correct value only for a0
recipient, and an off-by-one result for all pre-allocated recipients.The result in both cases above should be the same, however, they are
17888885298888888889
vs.
17888885298888888888
. Playground: https://play.golang.org/p/uSBvGkeGkNIssue originally found by @guidovranken, no security implication according to @rsc.
The text was updated successfully, but these errors were encountered: