CVE-2017-8932: Incorrect Calculation (CWE-682)
value: A bug in the standard library ScalarMult implementation of curve P-256 for amd64 architectures in Go before 1.7.6 and 1.8.x before 1.8.2 causes incorrect results to be generated for specific input points. An adaptive attack can be mounted to progressively extract the scalar input to ScalarMult by submitting crafted points and observing failures to the derive correct output. This leads to a full key recovery attack against static ECDH, as used in popular JWT libraries.
CWE description: The product performs a calculation that generates incorrect or unintended results that are later used in security-critical decisions or resource management.
CVSS v3 base score: 5.9
Published: 2017-07-06T16:29Z
Repository: https://github.com/golang/go
Language: Other
Files changed: src/crypto/elliptic/elliptic_test.go, src/crypto/elliptic/p256_asm_amd64.s
Commit date: 2017-04-19 18:07:31 +0000
Commit message: crypto/elliptic: fix carry bug in x86-64 P-256 implementation.

Patch from Vlad Krasnov and confirmed to be under CLA.

Fixes #20040.

Change-Id: Ieb8436c4dcb6669a1620f1e0d257efd047b1b87c
Reviewed-on: https://go-review.googlesource.com/41070
Run-TryBot: Adam Langley <agl@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>

Diff: diff --git a/src/crypto/elliptic/elliptic_test.go b/src/crypto/elliptic/elliptic_test.go
index 902c414383..c3e4c17d25 100644
--- a/src/crypto/elliptic/elliptic_test.go
+++ b/src/crypto/elliptic/elliptic_test.go
@@ -298,10 +298,33 @@ var p224BaseMultTests = []baseMultTest{
 		"b70e0cbd6bb4bf7f321390b94a03c1d356c21122343280d6115c1d21",
 		"42c89c774a08dc04b3dd201932bc8a5ea5f8b89bbb2a7e667aff81cd",
 	},
 }
 
+type scalarMultTest struct {
+	k          string
+	xIn, yIn   string
+	xOut, yOut string
+}
+
+var p256MultTests = []scalarMultTest{
+	{
+		"2a265f8bcbdcaf94d58519141e578124cb40d64a501fba9c11847b28965bc737",
+		"023819813ac969847059028ea88a1f30dfbcde03fc791d3a252c6b41211882ea",
+		"f93e4ae433cc12cf2a43fc0ef26400c0e125508224cdb649380f25479148a4ad",
+		"4d4de80f1534850d261075997e3049321a0864082d24a917863366c0724f5ae3",
+		"a22d2b7f7818a3563e0f7a76c9bf0921ac55e06e2e4d11795b233824b1db8cc0",
+	},
+	{
+		"313f72ff9fe811bf573176231b286a3bdb6f1b14e05c40146590727a71c3bccd",
+		"cc11887b2d66cbae8f4d306627192522932146b42f01d3c6f92bd5c8ba739b06",
+		"a2f08a029cd06b46183085bae9248b0ed15b70280c7ef13a457f5af382426031",
+		"831c3f6b5f762d2f461901577af41354ac5f228c2591f84f8a6e51e2e3f17991",
+		"93f90934cd0ef2c698cc471c60a93524e87ab31ca2412252337f364513e43684",
+	},
+}
+
 func TestBaseMult(t *testing.T) {
 	p224 := P224()
 	for i, e := range p224BaseMultTests {
 		k, ok := new(big.Int).SetString(e.k, 10)
 		if !ok {
@@ -377,10 +400,23 @@ func TestP256Mult(t *testing.T) {
 		}
 		if testing.Short() && i > 5 {
 			break
 		}
 	}
+
+	for i, e := range p256MultTests {
+		x, _ := new(big.Int).SetString(e.xIn, 16)
+		y, _ := new(big.Int).SetString(e.yIn, 16)
+		k, _ := new(big.Int).SetString(e.k, 16)
+		expectedX, _ := new(big.Int).SetString(e.xOut, 16)
+		expectedY, _ := new(big.Int).SetString(e.yOut, 16)
+
+		xx, yy := p256.ScalarMult(x, y, k.Bytes())
+		if xx.Cmp(expectedX) != 0 || yy.Cmp(expectedY) != 0 {
+			t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, xx, yy, expectedX, expectedY)
+		}
+	}
 }
 
 func TestInfinity(t *testing.T) {
 	tests := []struct {
 		name  string
diff --git a/src/crypto/elliptic/p256_asm_amd64.s b/src/crypto/elliptic/p256_asm_amd64.s
index 6c7bde16e5..ea4a6fab9a 100644
--- a/src/crypto/elliptic/p256_asm_amd64.s
+++ b/src/crypto/elliptic/p256_asm_amd64.s
@@ -1312,16 +1312,16 @@ TEXT p256SubInternal(SB),NOSPLIT,$0
 
 	ADDQ $-1, acc4
 	ADCQ p256const0<>(SB), acc5
 	ADCQ $0, acc6
 	ADCQ p256const1<>(SB), acc7
-	ADCQ $0, mul0
+	ANDQ $1, mul0
 
-	CMOVQNE acc0, acc4
-	CMOVQNE acc1, acc5
-	CMOVQNE acc2, acc6
-	CMOVQNE acc3, acc7
+	CMOVQEQ acc0, acc4
+	CMOVQEQ acc1, acc5
+	CMOVQEQ acc2, acc6
+	CMOVQEQ acc3, acc7
 
 	RET
 /* ---------------------------------------*/
 TEXT p256MulInternal(SB),NOSPLIT,$0
 	MOVQ acc4, mul0

Vulnerable code: 	ADCQ $0, mul0
	CMOVQNE acc0, acc4
	CMOVQNE acc1, acc5
	CMOVQNE acc2, acc6
	CMOVQNE acc3, acc7
Fixed code: type scalarMultTest struct {
	k          string
	xIn, yIn   string
	xOut, yOut string
}

var p256MultTests = []scalarMultTest{
	{
		"2a265f8bcbdcaf94d58519141e578124cb40d64a501fba9c11847b28965bc737",
		"023819813ac969847059028ea88a1f30dfbcde03fc791d3a252c6b41211882ea",
		"f93e4ae433cc12cf2a43fc0ef26400c0e125508224cdb649380f25479148a4ad",
		"4d4de80f1534850d261075997e3049321a0864082d24a917863366c0724f5ae3",
		"a22d2b7f7818a3563e0f7a76c9bf0921ac55e06e2e4d11795b233824b1db8cc0",
	},
	{
		"313f72ff9fe811bf573176231b286a3bdb6f1b14e05c40146590727a71c3bccd",
		"cc11887b2d66cbae8f4d306627192522932146b42f01d3c6f92bd5c8ba739b06",
		"a2f08a029cd06b46183085bae9248b0ed15b70280c7ef13a457f5af382426031",
		"831c3f6b5f762d2f461901577af41354ac5f228c2591f84f8a6e51e2e3f17991",
		"93f90934cd0ef2c698cc471c60a93524e87ab31ca2412252337f364513e43684",
	},
}


	for i, e := range p256MultTests {
		x, _ := new(big.Int).SetString(e.xIn, 16)
		y, _ := new(big.Int).SetString(e.yIn, 16)
		k, _ := new(big.Int).SetString(e.k, 16)
		expectedX, _ := new(big.Int).SetString(e.xOut, 16)
		expectedY, _ := new(big.Int).SetString(e.yOut, 16)

		xx, yy := p256.ScalarMult(x, y, k.Bytes())
		if xx.Cmp(expectedX) != 0 || yy.Cmp(expectedY) != 0 {
			t.Errorf("#%d: got (%x, %x), want (%x, %x)", i, xx, yy, expectedX, expectedY)
		}
	}
	ANDQ $1, mul0
	CMOVQEQ acc0, acc4
	CMOVQEQ acc1, acc5
	CMOVQEQ acc2, acc6
	CMOVQEQ acc3, acc7