CVE-2022-23806
authorGo Compiler Team <team+go-compiler@tracker.debian.org>
Thu, 20 Apr 2023 14:32:58 +0000 (15:32 +0100)
committerSylvain Beucler <beuc@debian.org>
Thu, 20 Apr 2023 14:32:58 +0000 (15:32 +0100)
Origin: https://github.com/golang/go/commit/6b3e741a834c34b8a844a33b3aa060dd4ed37231
Reviewed-by: Sylvain Beucler <beuc@debian.org>
Last-Update: 2023-04-18

From 6b3e741a834c34b8a844a33b3aa060dd4ed37231 Mon Sep 17 00:00:00 2001
From: Filippo Valsorda <filippo@golang.org>
Date: Wed, 2 Feb 2022 09:15:44 -0800
Subject: [PATCH] [release-branch.go1.16] crypto/elliptic: make IsOnCurve
 return false for invalid field elements

Updates #50974
Fixes #50977
Fixes CVE-2022-23806

Change-Id: I0201c2c88f13dd82910985a495973f1683af9259
Reviewed-on: https://go-review.googlesource.com/c/go/+/382855
Trust: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Katie Hockman <katie@golang.org>
Trust: Katie Hockman <katie@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>

Gbp-Pq: Name CVE-2022-23806.patch

src/crypto/elliptic/elliptic.go
src/crypto/elliptic/elliptic_test.go
src/crypto/elliptic/p224.go

index c84657c5e36777fcdf435b56ecf34d958f1b686f..ca16131d04aeec15bd9e961354aebadfaa9ea6bd 100644 (file)
@@ -53,6 +53,11 @@ func (curve *CurveParams) Params() *CurveParams {
 }
 
 func (curve *CurveParams) IsOnCurve(x, y *big.Int) bool {
+       if x.Sign() < 0 || x.Cmp(curve.P) >= 0 ||
+               y.Sign() < 0 || y.Cmp(curve.P) >= 0 {
+               return false
+       }
+
        // y² = x³ - 3x + b
        y2 := new(big.Int).Mul(y, y)
        y2.Mod(y2, curve.P)
index 09c5483520ee5cbe99430c453586e7f69395d8a1..b13a620f343c97afb315273e016e04d2e08235eb 100644 (file)
@@ -628,3 +628,84 @@ func TestUnmarshalToLargeCoordinates(t *testing.T) {
                t.Errorf("Unmarshal accepts invalid Y coordinate")
        }
 }
+
+func testAllCurves(t *testing.T, f func(*testing.T, Curve)) {
+       tests := []struct {
+               name  string
+               curve Curve
+       }{
+               {"P256", P256()},
+               {"P256/Params", P256().Params()},
+               {"P224", P224()},
+               {"P224/Params", P224().Params()},
+               {"P384", P384()},
+               {"P384/Params", P384().Params()},
+               {"P521", P521()},
+               {"P521/Params", P521().Params()},
+       }
+       if testing.Short() {
+               tests = tests[:1]
+       }
+       for _, test := range tests {
+               curve := test.curve
+               t.Run(test.name, func(t *testing.T) {
+                       t.Parallel()
+                       f(t, curve)
+               })
+       }
+}
+
+// TestInvalidCoordinates tests big.Int values that are not valid field elements
+// (negative or bigger than P). They are expected to return false from
+// IsOnCurve, all other behavior is undefined.
+func TestInvalidCoordinates(t *testing.T) {
+       testAllCurves(t, testInvalidCoordinates)
+}
+
+func testInvalidCoordinates(t *testing.T, curve Curve) {
+       checkIsOnCurveFalse := func(name string, x, y *big.Int) {
+               if curve.IsOnCurve(x, y) {
+                       t.Errorf("IsOnCurve(%s) unexpectedly returned true", name)
+               }
+       }
+
+       p := curve.Params().P
+       _, x, y, _ := GenerateKey(curve, rand.Reader)
+       xx, yy := new(big.Int), new(big.Int)
+
+       // Check if the sign is getting dropped.
+       xx.Neg(x)
+       checkIsOnCurveFalse("-x, y", xx, y)
+       yy.Neg(y)
+       checkIsOnCurveFalse("x, -y", x, yy)
+
+       // Check if negative values are reduced modulo P.
+       xx.Sub(x, p)
+       checkIsOnCurveFalse("x-P, y", xx, y)
+       yy.Sub(y, p)
+       checkIsOnCurveFalse("x, y-P", x, yy)
+
+       // Check if positive values are reduced modulo P.
+       xx.Add(x, p)
+       checkIsOnCurveFalse("x+P, y", xx, y)
+       yy.Add(y, p)
+       checkIsOnCurveFalse("x, y+P", x, yy)
+
+       // Check if the overflow is dropped.
+       xx.Add(x, new(big.Int).Lsh(big.NewInt(1), 535))
+       checkIsOnCurveFalse("x+2⁵³⁵, y", xx, y)
+       yy.Add(y, new(big.Int).Lsh(big.NewInt(1), 535))
+       checkIsOnCurveFalse("x, y+2⁵³⁵", x, yy)
+
+       // Check if P is treated like zero (if possible).
+       // y^2 = x^3 - 3x + B
+       // y = mod_sqrt(x^3 - 3x + B)
+       // y = mod_sqrt(B) if x = 0
+       // If there is no modsqrt, there is no point with x = 0, can't test x = P.
+       if yy := new(big.Int).ModSqrt(curve.Params().B, p); yy != nil {
+               if !curve.IsOnCurve(big.NewInt(0), yy) {
+                       t.Fatal("(0, mod_sqrt(B)) is not on the curve?")
+               }
+               checkIsOnCurveFalse("P, y", p, yy)
+       }
+}
index 8c76021464207f4f78a1bd0a7bc3d7d8e7bbb20e..ff5c8344522da8cc5abfe31055df3edf0c349543 100644 (file)
@@ -48,6 +48,11 @@ func (curve p224Curve) Params() *CurveParams {
 }
 
 func (curve p224Curve) IsOnCurve(bigX, bigY *big.Int) bool {
+       if bigX.Sign() < 0 || bigX.Cmp(curve.P) >= 0 ||
+               bigY.Sign() < 0 || bigY.Cmp(curve.P) >= 0 {
+               return false
+       }
+
        var x, y p224FieldElement
        p224FromBig(&x, bigX)
        p224FromBig(&y, bigY)