crypto/elliptic: reduce subtraction term to prevent long busy loop

If beta8 is unusually large, the addition loop might take a very long
time to bring x3-beta8 back positive.

This would lead to a DoS vulnerability in the implementation of the
P-521 and P-384 elliptic curves that may let an attacker craft inputs
to ScalarMult that consume excessive amounts of CPU.

This fixes CVE-2019-6486.

Fixes #29903

Change-Id: Ia969e8b5bf5ac4071a00722de9d5e4d856d8071a
Reviewed-on: https://team-review.git.corp.google.com/c/399777
Reviewed-by: Adam Langley <agl@google.com>
Reviewed-by: Julie Qiu <julieqiu@google.com>
Reviewed-on: https://go-review.googlesource.com/c/159218
Reviewed-by: Julie Qiu <julie@golang.org>
diff --git a/src/crypto/elliptic/elliptic.go b/src/crypto/elliptic/elliptic.go
index 4fc2b5e..c84657c 100644
--- a/src/crypto/elliptic/elliptic.go
+++ b/src/crypto/elliptic/elliptic.go
@@ -210,8 +210,9 @@
 
 	x3 := new(big.Int).Mul(alpha, alpha)
 	beta8 := new(big.Int).Lsh(beta, 3)
+	beta8.Mod(beta8, curve.P)
 	x3.Sub(x3, beta8)
-	for x3.Sign() == -1 {
+	if x3.Sign() == -1 {
 		x3.Add(x3, curve.P)
 	}
 	x3.Mod(x3, curve.P)