diff options
author | Ross Burton <ross.burton@arm.com> | 2023-03-27 13:03:35 +0100 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2023-03-28 22:28:45 +0100 |
commit | 985f1b883fe78af47f0956d9c7b5d5780e1baf0e (patch) | |
tree | 646a48518d310a03777ff3f4361d42a2efff3b29 | |
parent | 13d4b2a4552cb4f2c95e5793592ec4ba810702c8 (diff) | |
download | poky-985f1b883fe78af47f0956d9c7b5d5780e1baf0e.tar.gz |
go: fix CVE-2023-2453
Backport a security fix, can be removed once we have 1.20.2 onwards.
(From OE-Core rev: 06df8350c3bc6f56013a0bff20b64cfdbb81cfca)
Signed-off-by: Ross Burton <ross.burton@arm.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r-- | meta/recipes-devtools/go/go-1.20.1.inc | 1 | ||||
-rw-r--r-- | meta/recipes-devtools/go/go/CVE-2023-24532.patch | 208 |
2 files changed, 209 insertions, 0 deletions
diff --git a/meta/recipes-devtools/go/go-1.20.1.inc b/meta/recipes-devtools/go/go-1.20.1.inc index ffde7ed732..b1f569212d 100644 --- a/meta/recipes-devtools/go/go-1.20.1.inc +++ b/meta/recipes-devtools/go/go-1.20.1.inc | |||
@@ -15,5 +15,6 @@ SRC_URI += "\ | |||
15 | file://0008-src-cmd-dist-buildgo.go-do-not-hardcode-host-compile.patch \ | 15 | file://0008-src-cmd-dist-buildgo.go-do-not-hardcode-host-compile.patch \ |
16 | file://0009-go-Filter-build-paths-on-staticly-linked-arches.patch \ | 16 | file://0009-go-Filter-build-paths-on-staticly-linked-arches.patch \ |
17 | file://0010-cmd-compile-re-compile-instantiated-generic-methods-.patch \ | 17 | file://0010-cmd-compile-re-compile-instantiated-generic-methods-.patch \ |
18 | file://CVE-2023-24532.patch \ | ||
18 | " | 19 | " |
19 | SRC_URI[main.sha256sum] = "b5c1a3af52c385a6d1c76aed5361cf26459023980d0320de7658bae3915831a2" | 20 | SRC_URI[main.sha256sum] = "b5c1a3af52c385a6d1c76aed5361cf26459023980d0320de7658bae3915831a2" |
diff --git a/meta/recipes-devtools/go/go/CVE-2023-24532.patch b/meta/recipes-devtools/go/go/CVE-2023-24532.patch new file mode 100644 index 0000000000..22f080dbd4 --- /dev/null +++ b/meta/recipes-devtools/go/go/CVE-2023-24532.patch | |||
@@ -0,0 +1,208 @@ | |||
1 | From 602eeaab387f24a4b28c5eccbb50fa934f3bc3c4 Mon Sep 17 00:00:00 2001 | ||
2 | From: Filippo Valsorda <filippo@golang.org> | ||
3 | Date: Mon, 13 Feb 2023 15:16:27 +0100 | ||
4 | Subject: [PATCH] [release-branch.go1.20] crypto/internal/nistec: reduce P-256 | ||
5 | scalar | ||
6 | |||
7 | Unlike the rest of nistec, the P-256 assembly doesn't use complete | ||
8 | addition formulas, meaning that p256PointAdd[Affine]Asm won't return the | ||
9 | correct value if the two inputs are equal. | ||
10 | |||
11 | This was (undocumentedly) ignored in the scalar multiplication loops | ||
12 | because as long as the input point is not the identity and the scalar is | ||
13 | lower than the order of the group, the addition inputs can't be the same. | ||
14 | |||
15 | As part of the math/big rewrite, we went however from always reducing | ||
16 | the scalar to only checking its length, under the incorrect assumption | ||
17 | that the scalar multiplication loop didn't require reduction. | ||
18 | |||
19 | Added a reduction, and while at it added it in P256OrdInverse, too, to | ||
20 | enforce a universal reduction invariant on p256OrdElement values. | ||
21 | |||
22 | Note that if the input point is the infinity, the code currently still | ||
23 | relies on undefined behavior, but that's easily tested to behave | ||
24 | acceptably, and will be addressed in a future CL. | ||
25 | |||
26 | Updates #58647 | ||
27 | Fixes #58720 | ||
28 | Fixes CVE-2023-24532 | ||
29 | |||
30 | (Filed with the "safe APIs like complete addition formulas are good" dept.) | ||
31 | |||
32 | Change-Id: I7b2c75238440e6852be2710fad66ff1fdc4e2b24 | ||
33 | Reviewed-on: https://go-review.googlesource.com/c/go/+/471255 | ||
34 | TryBot-Result: Gopher Robot <gobot@golang.org> | ||
35 | Reviewed-by: Roland Shoemaker <roland@golang.org> | ||
36 | Run-TryBot: Filippo Valsorda <filippo@golang.org> | ||
37 | Auto-Submit: Filippo Valsorda <filippo@golang.org> | ||
38 | Reviewed-by: Damien Neil <dneil@google.com> | ||
39 | (cherry picked from commit 203e59ad41bd288e1d92b6f617c2f55e70d3c8e3) | ||
40 | Reviewed-on: https://go-review.googlesource.com/c/go/+/471695 | ||
41 | Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> | ||
42 | Auto-Submit: Dmitri Shuralyov <dmitshur@google.com> | ||
43 | Reviewed-by: Filippo Valsorda <filippo@golang.org> | ||
44 | Run-TryBot: Roland Shoemaker <roland@golang.org> | ||
45 | |||
46 | CVE: CVE-2023-24532 | ||
47 | Upstream-Status: Backport [602eeaab387f24a4b28c5eccbb50fa934f3bc3c4] | ||
48 | Signed-off-by: Ross Burton <ross.burton@arm.com> | ||
49 | |||
50 | --- | ||
51 | src/crypto/internal/nistec/nistec_test.go | 81 +++++++++++++++++++++++ | ||
52 | src/crypto/internal/nistec/p256_asm.go | 17 +++++ | ||
53 | src/crypto/internal/nistec/p256_ordinv.go | 1 + | ||
54 | 3 files changed, 99 insertions(+) | ||
55 | |||
56 | diff --git a/src/crypto/internal/nistec/nistec_test.go b/src/crypto/internal/nistec/nistec_test.go | ||
57 | index 309f68be16a9f..9103608c18a0f 100644 | ||
58 | --- a/src/crypto/internal/nistec/nistec_test.go | ||
59 | +++ b/src/crypto/internal/nistec/nistec_test.go | ||
60 | @@ -8,6 +8,7 @@ import ( | ||
61 | "bytes" | ||
62 | "crypto/elliptic" | ||
63 | "crypto/internal/nistec" | ||
64 | + "fmt" | ||
65 | "internal/testenv" | ||
66 | "math/big" | ||
67 | "math/rand" | ||
68 | @@ -165,6 +166,86 @@ func testEquivalents[P nistPoint[P]](t *testing.T, newPoint func() P, c elliptic | ||
69 | } | ||
70 | } | ||
71 | |||
72 | +func TestScalarMult(t *testing.T) { | ||
73 | + t.Run("P224", func(t *testing.T) { | ||
74 | + testScalarMult(t, nistec.NewP224Point, elliptic.P224()) | ||
75 | + }) | ||
76 | + t.Run("P256", func(t *testing.T) { | ||
77 | + testScalarMult(t, nistec.NewP256Point, elliptic.P256()) | ||
78 | + }) | ||
79 | + t.Run("P384", func(t *testing.T) { | ||
80 | + testScalarMult(t, nistec.NewP384Point, elliptic.P384()) | ||
81 | + }) | ||
82 | + t.Run("P521", func(t *testing.T) { | ||
83 | + testScalarMult(t, nistec.NewP521Point, elliptic.P521()) | ||
84 | + }) | ||
85 | +} | ||
86 | + | ||
87 | +func testScalarMult[P nistPoint[P]](t *testing.T, newPoint func() P, c elliptic.Curve) { | ||
88 | + G := newPoint().SetGenerator() | ||
89 | + checkScalar := func(t *testing.T, scalar []byte) { | ||
90 | + p1, err := newPoint().ScalarBaseMult(scalar) | ||
91 | + fatalIfErr(t, err) | ||
92 | + p2, err := newPoint().ScalarMult(G, scalar) | ||
93 | + fatalIfErr(t, err) | ||
94 | + if !bytes.Equal(p1.Bytes(), p2.Bytes()) { | ||
95 | + t.Error("[k]G != ScalarBaseMult(k)") | ||
96 | + } | ||
97 | + | ||
98 | + d := new(big.Int).SetBytes(scalar) | ||
99 | + d.Sub(c.Params().N, d) | ||
100 | + d.Mod(d, c.Params().N) | ||
101 | + g1, err := newPoint().ScalarBaseMult(d.FillBytes(make([]byte, len(scalar)))) | ||
102 | + fatalIfErr(t, err) | ||
103 | + g1.Add(g1, p1) | ||
104 | + if !bytes.Equal(g1.Bytes(), newPoint().Bytes()) { | ||
105 | + t.Error("[N - k]G + [k]G != ∞") | ||
106 | + } | ||
107 | + } | ||
108 | + | ||
109 | + byteLen := len(c.Params().N.Bytes()) | ||
110 | + bitLen := c.Params().N.BitLen() | ||
111 | + t.Run("0", func(t *testing.T) { checkScalar(t, make([]byte, byteLen)) }) | ||
112 | + t.Run("1", func(t *testing.T) { | ||
113 | + checkScalar(t, big.NewInt(1).FillBytes(make([]byte, byteLen))) | ||
114 | + }) | ||
115 | + t.Run("N-1", func(t *testing.T) { | ||
116 | + checkScalar(t, new(big.Int).Sub(c.Params().N, big.NewInt(1)).Bytes()) | ||
117 | + }) | ||
118 | + t.Run("N", func(t *testing.T) { checkScalar(t, c.Params().N.Bytes()) }) | ||
119 | + t.Run("N+1", func(t *testing.T) { | ||
120 | + checkScalar(t, new(big.Int).Add(c.Params().N, big.NewInt(1)).Bytes()) | ||
121 | + }) | ||
122 | + t.Run("all1s", func(t *testing.T) { | ||
123 | + s := new(big.Int).Lsh(big.NewInt(1), uint(bitLen)) | ||
124 | + s.Sub(s, big.NewInt(1)) | ||
125 | + checkScalar(t, s.Bytes()) | ||
126 | + }) | ||
127 | + if testing.Short() { | ||
128 | + return | ||
129 | + } | ||
130 | + for i := 0; i < bitLen; i++ { | ||
131 | + t.Run(fmt.Sprintf("1<<%d", i), func(t *testing.T) { | ||
132 | + s := new(big.Int).Lsh(big.NewInt(1), uint(i)) | ||
133 | + checkScalar(t, s.FillBytes(make([]byte, byteLen))) | ||
134 | + }) | ||
135 | + } | ||
136 | + // Test N+1...N+32 since they risk overlapping with precomputed table values | ||
137 | + // in the final additions. | ||
138 | + for i := int64(2); i <= 32; i++ { | ||
139 | + t.Run(fmt.Sprintf("N+%d", i), func(t *testing.T) { | ||
140 | + checkScalar(t, new(big.Int).Add(c.Params().N, big.NewInt(i)).Bytes()) | ||
141 | + }) | ||
142 | + } | ||
143 | +} | ||
144 | + | ||
145 | +func fatalIfErr(t *testing.T, err error) { | ||
146 | + t.Helper() | ||
147 | + if err != nil { | ||
148 | + t.Fatal(err) | ||
149 | + } | ||
150 | +} | ||
151 | + | ||
152 | func BenchmarkScalarMult(b *testing.B) { | ||
153 | b.Run("P224", func(b *testing.B) { | ||
154 | benchmarkScalarMult(b, nistec.NewP224Point().SetGenerator(), 28) | ||
155 | diff --git a/src/crypto/internal/nistec/p256_asm.go b/src/crypto/internal/nistec/p256_asm.go | ||
156 | index 6ea161eb49953..99a22b833f028 100644 | ||
157 | --- a/src/crypto/internal/nistec/p256_asm.go | ||
158 | +++ b/src/crypto/internal/nistec/p256_asm.go | ||
159 | @@ -364,6 +364,21 @@ func p256PointDoubleAsm(res, in *P256Point) | ||
160 | // Montgomery domain (with R 2²⁵⁶) as four uint64 limbs in little-endian order. | ||
161 | type p256OrdElement [4]uint64 | ||
162 | |||
163 | +// p256OrdReduce ensures s is in the range [0, ord(G)-1]. | ||
164 | +func p256OrdReduce(s *p256OrdElement) { | ||
165 | + // Since 2 * ord(G) > 2²⁵⁶, we can just conditionally subtract ord(G), | ||
166 | + // keeping the result if it doesn't underflow. | ||
167 | + t0, b := bits.Sub64(s[0], 0xf3b9cac2fc632551, 0) | ||
168 | + t1, b := bits.Sub64(s[1], 0xbce6faada7179e84, b) | ||
169 | + t2, b := bits.Sub64(s[2], 0xffffffffffffffff, b) | ||
170 | + t3, b := bits.Sub64(s[3], 0xffffffff00000000, b) | ||
171 | + tMask := b - 1 // zero if subtraction underflowed | ||
172 | + s[0] ^= (t0 ^ s[0]) & tMask | ||
173 | + s[1] ^= (t1 ^ s[1]) & tMask | ||
174 | + s[2] ^= (t2 ^ s[2]) & tMask | ||
175 | + s[3] ^= (t3 ^ s[3]) & tMask | ||
176 | +} | ||
177 | + | ||
178 | // Add sets q = p1 + p2, and returns q. The points may overlap. | ||
179 | func (q *P256Point) Add(r1, r2 *P256Point) *P256Point { | ||
180 | var sum, double P256Point | ||
181 | @@ -393,6 +408,7 @@ func (r *P256Point) ScalarBaseMult(scalar []byte) (*P256Point, error) { | ||
182 | } | ||
183 | scalarReversed := new(p256OrdElement) | ||
184 | p256OrdBigToLittle(scalarReversed, (*[32]byte)(scalar)) | ||
185 | + p256OrdReduce(scalarReversed) | ||
186 | |||
187 | r.p256BaseMult(scalarReversed) | ||
188 | return r, nil | ||
189 | @@ -407,6 +423,7 @@ func (r *P256Point) ScalarMult(q *P256Point, scalar []byte) (*P256Point, error) | ||
190 | } | ||
191 | scalarReversed := new(p256OrdElement) | ||
192 | p256OrdBigToLittle(scalarReversed, (*[32]byte)(scalar)) | ||
193 | + p256OrdReduce(scalarReversed) | ||
194 | |||
195 | r.Set(q).p256ScalarMult(scalarReversed) | ||
196 | return r, nil | ||
197 | diff --git a/src/crypto/internal/nistec/p256_ordinv.go b/src/crypto/internal/nistec/p256_ordinv.go | ||
198 | index 86a7a230bdce8..1274fb7fd3f5c 100644 | ||
199 | --- a/src/crypto/internal/nistec/p256_ordinv.go | ||
200 | +++ b/src/crypto/internal/nistec/p256_ordinv.go | ||
201 | @@ -25,6 +25,7 @@ func P256OrdInverse(k []byte) ([]byte, error) { | ||
202 | |||
203 | x := new(p256OrdElement) | ||
204 | p256OrdBigToLittle(x, (*[32]byte)(k)) | ||
205 | + p256OrdReduce(x) | ||
206 | |||
207 | // Inversion is implemented as exponentiation by n - 2, per Fermat's little theorem. | ||
208 | // | ||