diff options
author | Vijay Anusuri <vanusuri@mvista.com> | 2024-01-06 11:19:31 +0530 |
---|---|---|
committer | Steve Sakoman <steve@sakoman.com> | 2024-01-21 08:33:18 -1000 |
commit | 5c5aa47adb05bb966711e5ead98333a53c07ab1d (patch) | |
tree | 103c69bad311467feaa3fb768e33b52eac9391f5 /meta | |
parent | b418ede9942f8b31d66ce172ede35f55b423b0a2 (diff) | |
download | poky-5c5aa47adb05bb966711e5ead98333a53c07ab1d.tar.gz |
go: Backport fix for CVE-2023-45287
Upstream-Status: Backport
[https://github.com/golang/go/commit/9baafabac9a84813a336f068862207d2bb06d255
&
https://github.com/golang/go/commit/c9d5f60eaa4450ccf1ce878d55b4c6a12843f2f3
&
https://github.com/golang/go/commit/8f676144ad7b7c91adb0c6e1ec89aaa6283c6807
&
https://github.com/golang/go/commit/8a81fdf165facdcefa06531de5af98a4db343035]
(From OE-Core rev: 20e1d10a3ebefc8c5237c065c25eba4182d22efd)
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
Diffstat (limited to 'meta')
-rw-r--r-- | meta/recipes-devtools/go/go-1.14.inc | 4 | ||||
-rw-r--r-- | meta/recipes-devtools/go/go-1.14/CVE-2023-45287-pre1.patch | 393 | ||||
-rw-r--r-- | meta/recipes-devtools/go/go-1.14/CVE-2023-45287-pre2.patch | 401 | ||||
-rw-r--r-- | meta/recipes-devtools/go/go-1.14/CVE-2023-45287-pre3.patch | 86 | ||||
-rw-r--r-- | meta/recipes-devtools/go/go-1.14/CVE-2023-45287.patch | 1697 |
5 files changed, 2581 insertions, 0 deletions
diff --git a/meta/recipes-devtools/go/go-1.14.inc b/meta/recipes-devtools/go/go-1.14.inc index b827a3606d..42a9ac8435 100644 --- a/meta/recipes-devtools/go/go-1.14.inc +++ b/meta/recipes-devtools/go/go-1.14.inc | |||
@@ -83,6 +83,10 @@ SRC_URI += "\ | |||
83 | file://CVE-2023-39318.patch \ | 83 | file://CVE-2023-39318.patch \ |
84 | file://CVE-2023-39319.patch \ | 84 | file://CVE-2023-39319.patch \ |
85 | file://CVE-2023-39326.patch \ | 85 | file://CVE-2023-39326.patch \ |
86 | file://CVE-2023-45287-pre1.patch \ | ||
87 | file://CVE-2023-45287-pre2.patch \ | ||
88 | file://CVE-2023-45287-pre3.patch \ | ||
89 | file://CVE-2023-45287.patch \ | ||
86 | " | 90 | " |
87 | 91 | ||
88 | SRC_URI_append_libc-musl = " file://0009-ld-replace-glibc-dynamic-linker-with-musl.patch" | 92 | SRC_URI_append_libc-musl = " file://0009-ld-replace-glibc-dynamic-linker-with-musl.patch" |
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-45287-pre1.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-45287-pre1.patch new file mode 100644 index 0000000000..4d65180253 --- /dev/null +++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-45287-pre1.patch | |||
@@ -0,0 +1,393 @@ | |||
1 | From 9baafabac9a84813a336f068862207d2bb06d255 Mon Sep 17 00:00:00 2001 | ||
2 | From: Filippo Valsorda <filippo@golang.org> | ||
3 | Date: Wed, 1 Apr 2020 17:25:40 -0400 | ||
4 | Subject: [PATCH] crypto/rsa: refactor RSA-PSS signing and verification | ||
5 | |||
6 | Cleaned up for readability and consistency. | ||
7 | |||
8 | There is one tiny behavioral change: when PSSSaltLengthEqualsHash is | ||
9 | used and both hash and opts.Hash were set, hash.Size() was used for the | ||
10 | salt length instead of opts.Hash.Size(). That's clearly wrong because | ||
11 | opts.Hash is documented to override hash. | ||
12 | |||
13 | Change-Id: I3e25dad933961eac827c6d2e3bbfe45fc5a6fb0e | ||
14 | Reviewed-on: https://go-review.googlesource.com/c/go/+/226937 | ||
15 | Run-TryBot: Filippo Valsorda <filippo@golang.org> | ||
16 | TryBot-Result: Gobot Gobot <gobot@golang.org> | ||
17 | Reviewed-by: Katie Hockman <katie@golang.org> | ||
18 | |||
19 | Upstream-Status: Backport [https://github.com/golang/go/commit/9baafabac9a84813a336f068862207d2bb06d255] | ||
20 | CVE: CVE-2023-45287 #Dependency Patch1 | ||
21 | Signed-off-by: Vijay Anusuri <vanusuri@mvista.com> | ||
22 | --- | ||
23 | src/crypto/rsa/pss.go | 173 ++++++++++++++++++++++-------------------- | ||
24 | src/crypto/rsa/rsa.go | 9 ++- | ||
25 | 2 files changed, 96 insertions(+), 86 deletions(-) | ||
26 | |||
27 | diff --git a/src/crypto/rsa/pss.go b/src/crypto/rsa/pss.go | ||
28 | index 3ff0c2f4d0076..f9844d87329a8 100644 | ||
29 | --- a/src/crypto/rsa/pss.go | ||
30 | +++ b/src/crypto/rsa/pss.go | ||
31 | @@ -4,9 +4,7 @@ | ||
32 | |||
33 | package rsa | ||
34 | |||
35 | -// This file implements the PSS signature scheme [1]. | ||
36 | -// | ||
37 | -// [1] https://www.emc.com/collateral/white-papers/h11300-pkcs-1v2-2-rsa-cryptography-standard-wp.pdf | ||
38 | +// This file implements the RSASSA-PSS signature scheme according to RFC 8017. | ||
39 | |||
40 | import ( | ||
41 | "bytes" | ||
42 | @@ -17,8 +15,22 @@ import ( | ||
43 | "math/big" | ||
44 | ) | ||
45 | |||
46 | +// Per RFC 8017, Section 9.1 | ||
47 | +// | ||
48 | +// EM = MGF1 xor DB || H( 8*0x00 || mHash || salt ) || 0xbc | ||
49 | +// | ||
50 | +// where | ||
51 | +// | ||
52 | +// DB = PS || 0x01 || salt | ||
53 | +// | ||
54 | +// and PS can be empty so | ||
55 | +// | ||
56 | +// emLen = dbLen + hLen + 1 = psLen + sLen + hLen + 2 | ||
57 | +// | ||
58 | + | ||
59 | func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byte, error) { | ||
60 | - // See [1], section 9.1.1 | ||
61 | + // See RFC 8017, Section 9.1.1. | ||
62 | + | ||
63 | hLen := hash.Size() | ||
64 | sLen := len(salt) | ||
65 | emLen := (emBits + 7) / 8 | ||
66 | @@ -30,7 +42,7 @@ func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byt | ||
67 | // 2. Let mHash = Hash(M), an octet string of length hLen. | ||
68 | |||
69 | if len(mHash) != hLen { | ||
70 | - return nil, errors.New("crypto/rsa: input must be hashed message") | ||
71 | + return nil, errors.New("crypto/rsa: input must be hashed with given hash") | ||
72 | } | ||
73 | |||
74 | // 3. If emLen < hLen + sLen + 2, output "encoding error" and stop. | ||
75 | @@ -40,8 +52,9 @@ func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byt | ||
76 | } | ||
77 | |||
78 | em := make([]byte, emLen) | ||
79 | - db := em[:emLen-sLen-hLen-2+1+sLen] | ||
80 | - h := em[emLen-sLen-hLen-2+1+sLen : emLen-1] | ||
81 | + psLen := emLen - sLen - hLen - 2 | ||
82 | + db := em[:psLen+1+sLen] | ||
83 | + h := em[psLen+1+sLen : emLen-1] | ||
84 | |||
85 | // 4. Generate a random octet string salt of length sLen; if sLen = 0, | ||
86 | // then salt is the empty string. | ||
87 | @@ -69,8 +82,8 @@ func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byt | ||
88 | // 8. Let DB = PS || 0x01 || salt; DB is an octet string of length | ||
89 | // emLen - hLen - 1. | ||
90 | |||
91 | - db[emLen-sLen-hLen-2] = 0x01 | ||
92 | - copy(db[emLen-sLen-hLen-1:], salt) | ||
93 | + db[psLen] = 0x01 | ||
94 | + copy(db[psLen+1:], salt) | ||
95 | |||
96 | // 9. Let dbMask = MGF(H, emLen - hLen - 1). | ||
97 | // | ||
98 | @@ -81,47 +94,57 @@ func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byt | ||
99 | // 11. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in | ||
100 | // maskedDB to zero. | ||
101 | |||
102 | - db[0] &= (0xFF >> uint(8*emLen-emBits)) | ||
103 | + db[0] &= 0xff >> (8*emLen - emBits) | ||
104 | |||
105 | // 12. Let EM = maskedDB || H || 0xbc. | ||
106 | - em[emLen-1] = 0xBC | ||
107 | + em[emLen-1] = 0xbc | ||
108 | |||
109 | // 13. Output EM. | ||
110 | return em, nil | ||
111 | } | ||
112 | |||
113 | func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error { | ||
114 | + // See RFC 8017, Section 9.1.2. | ||
115 | + | ||
116 | + hLen := hash.Size() | ||
117 | + if sLen == PSSSaltLengthEqualsHash { | ||
118 | + sLen = hLen | ||
119 | + } | ||
120 | + emLen := (emBits + 7) / 8 | ||
121 | + if emLen != len(em) { | ||
122 | + return errors.New("rsa: internal error: inconsistent length") | ||
123 | + } | ||
124 | + | ||
125 | // 1. If the length of M is greater than the input limitation for the | ||
126 | // hash function (2^61 - 1 octets for SHA-1), output "inconsistent" | ||
127 | // and stop. | ||
128 | // | ||
129 | // 2. Let mHash = Hash(M), an octet string of length hLen. | ||
130 | - hLen := hash.Size() | ||
131 | if hLen != len(mHash) { | ||
132 | return ErrVerification | ||
133 | } | ||
134 | |||
135 | // 3. If emLen < hLen + sLen + 2, output "inconsistent" and stop. | ||
136 | - emLen := (emBits + 7) / 8 | ||
137 | if emLen < hLen+sLen+2 { | ||
138 | return ErrVerification | ||
139 | } | ||
140 | |||
141 | // 4. If the rightmost octet of EM does not have hexadecimal value | ||
142 | // 0xbc, output "inconsistent" and stop. | ||
143 | - if em[len(em)-1] != 0xBC { | ||
144 | + if em[emLen-1] != 0xbc { | ||
145 | return ErrVerification | ||
146 | } | ||
147 | |||
148 | // 5. Let maskedDB be the leftmost emLen - hLen - 1 octets of EM, and | ||
149 | // let H be the next hLen octets. | ||
150 | db := em[:emLen-hLen-1] | ||
151 | - h := em[emLen-hLen-1 : len(em)-1] | ||
152 | + h := em[emLen-hLen-1 : emLen-1] | ||
153 | |||
154 | // 6. If the leftmost 8 * emLen - emBits bits of the leftmost octet in | ||
155 | // maskedDB are not all equal to zero, output "inconsistent" and | ||
156 | // stop. | ||
157 | - if em[0]&(0xFF<<uint(8-(8*emLen-emBits))) != 0 { | ||
158 | + var bitMask byte = 0xff >> (8*emLen - emBits) | ||
159 | + if em[0] & ^bitMask != 0 { | ||
160 | return ErrVerification | ||
161 | } | ||
162 | |||
163 | @@ -132,37 +155,30 @@ func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error { | ||
164 | |||
165 | // 9. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in DB | ||
166 | // to zero. | ||
167 | - db[0] &= (0xFF >> uint(8*emLen-emBits)) | ||
168 | + db[0] &= bitMask | ||
169 | |||
170 | + // If we don't know the salt length, look for the 0x01 delimiter. | ||
171 | if sLen == PSSSaltLengthAuto { | ||
172 | - FindSaltLength: | ||
173 | - for sLen = emLen - (hLen + 2); sLen >= 0; sLen-- { | ||
174 | - switch db[emLen-hLen-sLen-2] { | ||
175 | - case 1: | ||
176 | - break FindSaltLength | ||
177 | - case 0: | ||
178 | - continue | ||
179 | - default: | ||
180 | - return ErrVerification | ||
181 | - } | ||
182 | - } | ||
183 | - if sLen < 0 { | ||
184 | + psLen := bytes.IndexByte(db, 0x01) | ||
185 | + if psLen < 0 { | ||
186 | return ErrVerification | ||
187 | } | ||
188 | - } else { | ||
189 | - // 10. If the emLen - hLen - sLen - 2 leftmost octets of DB are not zero | ||
190 | - // or if the octet at position emLen - hLen - sLen - 1 (the leftmost | ||
191 | - // position is "position 1") does not have hexadecimal value 0x01, | ||
192 | - // output "inconsistent" and stop. | ||
193 | - for _, e := range db[:emLen-hLen-sLen-2] { | ||
194 | - if e != 0x00 { | ||
195 | - return ErrVerification | ||
196 | - } | ||
197 | - } | ||
198 | - if db[emLen-hLen-sLen-2] != 0x01 { | ||
199 | + sLen = len(db) - psLen - 1 | ||
200 | + } | ||
201 | + | ||
202 | + // 10. If the emLen - hLen - sLen - 2 leftmost octets of DB are not zero | ||
203 | + // or if the octet at position emLen - hLen - sLen - 1 (the leftmost | ||
204 | + // position is "position 1") does not have hexadecimal value 0x01, | ||
205 | + // output "inconsistent" and stop. | ||
206 | + psLen := emLen - hLen - sLen - 2 | ||
207 | + for _, e := range db[:psLen] { | ||
208 | + if e != 0x00 { | ||
209 | return ErrVerification | ||
210 | } | ||
211 | } | ||
212 | + if db[psLen] != 0x01 { | ||
213 | + return ErrVerification | ||
214 | + } | ||
215 | |||
216 | // 11. Let salt be the last sLen octets of DB. | ||
217 | salt := db[len(db)-sLen:] | ||
218 | @@ -181,19 +197,19 @@ func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error { | ||
219 | h0 := hash.Sum(nil) | ||
220 | |||
221 | // 14. If H = H', output "consistent." Otherwise, output "inconsistent." | ||
222 | - if !bytes.Equal(h0, h) { | ||
223 | + if !bytes.Equal(h0, h) { // TODO: constant time? | ||
224 | return ErrVerification | ||
225 | } | ||
226 | return nil | ||
227 | } | ||
228 | |||
229 | -// signPSSWithSalt calculates the signature of hashed using PSS [1] with specified salt. | ||
230 | +// signPSSWithSalt calculates the signature of hashed using PSS with specified salt. | ||
231 | // Note that hashed must be the result of hashing the input message using the | ||
232 | // given hash function. salt is a random sequence of bytes whose length will be | ||
233 | // later used to verify the signature. | ||
234 | func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) (s []byte, err error) { | ||
235 | - nBits := priv.N.BitLen() | ||
236 | - em, err := emsaPSSEncode(hashed, nBits-1, salt, hash.New()) | ||
237 | + emBits := priv.N.BitLen() - 1 | ||
238 | + em, err := emsaPSSEncode(hashed, emBits, salt, hash.New()) | ||
239 | if err != nil { | ||
240 | return | ||
241 | } | ||
242 | @@ -202,7 +218,7 @@ func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed, | ||
243 | if err != nil { | ||
244 | return | ||
245 | } | ||
246 | - s = make([]byte, (nBits+7)/8) | ||
247 | + s = make([]byte, priv.Size()) | ||
248 | copyWithLeftPad(s, c.Bytes()) | ||
249 | return | ||
250 | } | ||
251 | @@ -223,16 +239,15 @@ type PSSOptions struct { | ||
252 | // PSSSaltLength constants. | ||
253 | SaltLength int | ||
254 | |||
255 | - // Hash, if not zero, overrides the hash function passed to SignPSS. | ||
256 | - // This is the only way to specify the hash function when using the | ||
257 | - // crypto.Signer interface. | ||
258 | + // Hash is the hash function used to generate the message digest. If not | ||
259 | + // zero, it overrides the hash function passed to SignPSS. It's required | ||
260 | + // when using PrivateKey.Sign. | ||
261 | Hash crypto.Hash | ||
262 | } | ||
263 | |||
264 | -// HashFunc returns pssOpts.Hash so that PSSOptions implements | ||
265 | -// crypto.SignerOpts. | ||
266 | -func (pssOpts *PSSOptions) HashFunc() crypto.Hash { | ||
267 | - return pssOpts.Hash | ||
268 | +// HashFunc returns opts.Hash so that PSSOptions implements crypto.SignerOpts. | ||
269 | +func (opts *PSSOptions) HashFunc() crypto.Hash { | ||
270 | + return opts.Hash | ||
271 | } | ||
272 | |||
273 | func (opts *PSSOptions) saltLength() int { | ||
274 | @@ -242,56 +257,50 @@ func (opts *PSSOptions) saltLength() int { | ||
275 | return opts.SaltLength | ||
276 | } | ||
277 | |||
278 | -// SignPSS calculates the signature of hashed using RSASSA-PSS [1]. | ||
279 | -// Note that hashed must be the result of hashing the input message using the | ||
280 | -// given hash function. The opts argument may be nil, in which case sensible | ||
281 | -// defaults are used. | ||
282 | -func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte, opts *PSSOptions) ([]byte, error) { | ||
283 | +// SignPSS calculates the signature of digest using PSS. | ||
284 | +// | ||
285 | +// digest must be the result of hashing the input message using the given hash | ||
286 | +// function. The opts argument may be nil, in which case sensible defaults are | ||
287 | +// used. If opts.Hash is set, it overrides hash. | ||
288 | +func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, opts *PSSOptions) ([]byte, error) { | ||
289 | + if opts != nil && opts.Hash != 0 { | ||
290 | + hash = opts.Hash | ||
291 | + } | ||
292 | + | ||
293 | saltLength := opts.saltLength() | ||
294 | switch saltLength { | ||
295 | case PSSSaltLengthAuto: | ||
296 | - saltLength = (priv.N.BitLen()+7)/8 - 2 - hash.Size() | ||
297 | + saltLength = priv.Size() - 2 - hash.Size() | ||
298 | case PSSSaltLengthEqualsHash: | ||
299 | saltLength = hash.Size() | ||
300 | } | ||
301 | |||
302 | - if opts != nil && opts.Hash != 0 { | ||
303 | - hash = opts.Hash | ||
304 | - } | ||
305 | - | ||
306 | salt := make([]byte, saltLength) | ||
307 | if _, err := io.ReadFull(rand, salt); err != nil { | ||
308 | return nil, err | ||
309 | } | ||
310 | - return signPSSWithSalt(rand, priv, hash, hashed, salt) | ||
311 | + return signPSSWithSalt(rand, priv, hash, digest, salt) | ||
312 | } | ||
313 | |||
314 | // VerifyPSS verifies a PSS signature. | ||
315 | -// hashed is the result of hashing the input message using the given hash | ||
316 | -// function and sig is the signature. A valid signature is indicated by | ||
317 | -// returning a nil error. The opts argument may be nil, in which case sensible | ||
318 | -// defaults are used. | ||
319 | -func VerifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, opts *PSSOptions) error { | ||
320 | - return verifyPSS(pub, hash, hashed, sig, opts.saltLength()) | ||
321 | -} | ||
322 | - | ||
323 | -// verifyPSS verifies a PSS signature with the given salt length. | ||
324 | -func verifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, saltLen int) error { | ||
325 | - nBits := pub.N.BitLen() | ||
326 | - if len(sig) != (nBits+7)/8 { | ||
327 | +// | ||
328 | +// A valid signature is indicated by returning a nil error. digest must be the | ||
329 | +// result of hashing the input message using the given hash function. The opts | ||
330 | +// argument may be nil, in which case sensible defaults are used. opts.Hash is | ||
331 | +// ignored. | ||
332 | +func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts *PSSOptions) error { | ||
333 | + if len(sig) != pub.Size() { | ||
334 | return ErrVerification | ||
335 | } | ||
336 | s := new(big.Int).SetBytes(sig) | ||
337 | m := encrypt(new(big.Int), pub, s) | ||
338 | - emBits := nBits - 1 | ||
339 | + emBits := pub.N.BitLen() - 1 | ||
340 | emLen := (emBits + 7) / 8 | ||
341 | - if emLen < len(m.Bytes()) { | ||
342 | + emBytes := m.Bytes() | ||
343 | + if emLen < len(emBytes) { | ||
344 | return ErrVerification | ||
345 | } | ||
346 | em := make([]byte, emLen) | ||
347 | - copyWithLeftPad(em, m.Bytes()) | ||
348 | - if saltLen == PSSSaltLengthEqualsHash { | ||
349 | - saltLen = hash.Size() | ||
350 | - } | ||
351 | - return emsaPSSVerify(hashed, em, emBits, saltLen, hash.New()) | ||
352 | + copyWithLeftPad(em, emBytes) | ||
353 | + return emsaPSSVerify(digest, em, emBits, opts.saltLength(), hash.New()) | ||
354 | } | ||
355 | diff --git a/src/crypto/rsa/rsa.go b/src/crypto/rsa/rsa.go | ||
356 | index 5a42990640164..b4bfa13defbdf 100644 | ||
357 | --- a/src/crypto/rsa/rsa.go | ||
358 | +++ b/src/crypto/rsa/rsa.go | ||
359 | @@ -2,7 +2,7 @@ | ||
360 | // Use of this source code is governed by a BSD-style | ||
361 | // license that can be found in the LICENSE file. | ||
362 | |||
363 | -// Package rsa implements RSA encryption as specified in PKCS#1. | ||
364 | +// Package rsa implements RSA encryption as specified in PKCS#1 and RFC 8017. | ||
365 | // | ||
366 | // RSA is a single, fundamental operation that is used in this package to | ||
367 | // implement either public-key encryption or public-key signatures. | ||
368 | @@ -10,13 +10,13 @@ | ||
369 | // The original specification for encryption and signatures with RSA is PKCS#1 | ||
370 | // and the terms "RSA encryption" and "RSA signatures" by default refer to | ||
371 | // PKCS#1 version 1.5. However, that specification has flaws and new designs | ||
372 | -// should use version two, usually called by just OAEP and PSS, where | ||
373 | +// should use version 2, usually called by just OAEP and PSS, where | ||
374 | // possible. | ||
375 | // | ||
376 | // Two sets of interfaces are included in this package. When a more abstract | ||
377 | // interface isn't necessary, there are functions for encrypting/decrypting | ||
378 | // with v1.5/OAEP and signing/verifying with v1.5/PSS. If one needs to abstract | ||
379 | -// over the public-key primitive, the PrivateKey struct implements the | ||
380 | +// over the public key primitive, the PrivateKey type implements the | ||
381 | // Decrypter and Signer interfaces from the crypto package. | ||
382 | // | ||
383 | // The RSA operations in this package are not implemented using constant-time algorithms. | ||
384 | @@ -111,7 +111,8 @@ func (priv *PrivateKey) Public() crypto.PublicKey { | ||
385 | |||
386 | // Sign signs digest with priv, reading randomness from rand. If opts is a | ||
387 | // *PSSOptions then the PSS algorithm will be used, otherwise PKCS#1 v1.5 will | ||
388 | -// be used. | ||
389 | +// be used. digest must be the result of hashing the input message using | ||
390 | +// opts.HashFunc(). | ||
391 | // | ||
392 | // This method implements crypto.Signer, which is an interface to support keys | ||
393 | // where the private part is kept in, for example, a hardware module. Common | ||
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-45287-pre2.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-45287-pre2.patch new file mode 100644 index 0000000000..1327b44545 --- /dev/null +++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-45287-pre2.patch | |||
@@ -0,0 +1,401 @@ | |||
1 | From c9d5f60eaa4450ccf1ce878d55b4c6a12843f2f3 Mon Sep 17 00:00:00 2001 | ||
2 | From: Filippo Valsorda <filippo@golang.org> | ||
3 | Date: Mon, 27 Apr 2020 21:52:38 -0400 | ||
4 | Subject: [PATCH] math/big: add (*Int).FillBytes | ||
5 | |||
6 | Replaced almost every use of Bytes with FillBytes. | ||
7 | |||
8 | Note that the approved proposal was for | ||
9 | |||
10 | func (*Int) FillBytes(buf []byte) | ||
11 | |||
12 | while this implements | ||
13 | |||
14 | func (*Int) FillBytes(buf []byte) []byte | ||
15 | |||
16 | because the latter was far nicer to use in all callsites. | ||
17 | |||
18 | Fixes #35833 | ||
19 | |||
20 | Change-Id: Ia912df123e5d79b763845312ea3d9a8051343c0a | ||
21 | Reviewed-on: https://go-review.googlesource.com/c/go/+/230397 | ||
22 | Reviewed-by: Robert Griesemer <gri@golang.org> | ||
23 | |||
24 | Upstream-Status: Backport [https://github.com/golang/go/commit/c9d5f60eaa4450ccf1ce878d55b4c6a12843f2f3] | ||
25 | CVE: CVE-2023-45287 #Dependency Patch2 | ||
26 | Signed-off-by: Vijay Anusuri <vanusuri@mvista.com> | ||
27 | --- | ||
28 | src/crypto/elliptic/elliptic.go | 13 ++++---- | ||
29 | src/crypto/rsa/pkcs1v15.go | 20 +++--------- | ||
30 | src/crypto/rsa/pss.go | 17 +++++------ | ||
31 | src/crypto/rsa/rsa.go | 32 +++---------------- | ||
32 | src/crypto/tls/key_schedule.go | 7 ++--- | ||
33 | src/crypto/x509/sec1.go | 7 ++--- | ||
34 | src/math/big/int.go | 15 +++++++++ | ||
35 | src/math/big/int_test.go | 54 +++++++++++++++++++++++++++++++++ | ||
36 | src/math/big/nat.go | 15 ++++++--- | ||
37 | 9 files changed, 106 insertions(+), 74 deletions(-) | ||
38 | |||
39 | diff --git a/src/crypto/elliptic/elliptic.go b/src/crypto/elliptic/elliptic.go | ||
40 | index e2f71cdb63bab..bd5168c5fd842 100644 | ||
41 | --- a/src/crypto/elliptic/elliptic.go | ||
42 | +++ b/src/crypto/elliptic/elliptic.go | ||
43 | @@ -277,7 +277,7 @@ var mask = []byte{0xff, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f} | ||
44 | func GenerateKey(curve Curve, rand io.Reader) (priv []byte, x, y *big.Int, err error) { | ||
45 | N := curve.Params().N | ||
46 | bitSize := N.BitLen() | ||
47 | - byteLen := (bitSize + 7) >> 3 | ||
48 | + byteLen := (bitSize + 7) / 8 | ||
49 | priv = make([]byte, byteLen) | ||
50 | |||
51 | for x == nil { | ||
52 | @@ -304,15 +304,14 @@ func GenerateKey(curve Curve, rand io.Reader) (priv []byte, x, y *big.Int, err e | ||
53 | |||
54 | // Marshal converts a point into the uncompressed form specified in section 4.3.6 of ANSI X9.62. | ||
55 | func Marshal(curve Curve, x, y *big.Int) []byte { | ||
56 | - byteLen := (curve.Params().BitSize + 7) >> 3 | ||
57 | + byteLen := (curve.Params().BitSize + 7) / 8 | ||
58 | |||
59 | ret := make([]byte, 1+2*byteLen) | ||
60 | ret[0] = 4 // uncompressed point | ||
61 | |||
62 | - xBytes := x.Bytes() | ||
63 | - copy(ret[1+byteLen-len(xBytes):], xBytes) | ||
64 | - yBytes := y.Bytes() | ||
65 | - copy(ret[1+2*byteLen-len(yBytes):], yBytes) | ||
66 | + x.FillBytes(ret[1 : 1+byteLen]) | ||
67 | + y.FillBytes(ret[1+byteLen : 1+2*byteLen]) | ||
68 | + | ||
69 | return ret | ||
70 | } | ||
71 | |||
72 | @@ -320,7 +319,7 @@ func Marshal(curve Curve, x, y *big.Int) []byte { | ||
73 | // It is an error if the point is not in uncompressed form or is not on the curve. | ||
74 | // On error, x = nil. | ||
75 | func Unmarshal(curve Curve, data []byte) (x, y *big.Int) { | ||
76 | - byteLen := (curve.Params().BitSize + 7) >> 3 | ||
77 | + byteLen := (curve.Params().BitSize + 7) / 8 | ||
78 | if len(data) != 1+2*byteLen { | ||
79 | return | ||
80 | } | ||
81 | diff --git a/src/crypto/rsa/pkcs1v15.go b/src/crypto/rsa/pkcs1v15.go | ||
82 | index 499242ffc5b57..3208119ae1ff4 100644 | ||
83 | --- a/src/crypto/rsa/pkcs1v15.go | ||
84 | +++ b/src/crypto/rsa/pkcs1v15.go | ||
85 | @@ -61,8 +61,7 @@ func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) ([]byte, error) | ||
86 | m := new(big.Int).SetBytes(em) | ||
87 | c := encrypt(new(big.Int), pub, m) | ||
88 | |||
89 | - copyWithLeftPad(em, c.Bytes()) | ||
90 | - return em, nil | ||
91 | + return c.FillBytes(em), nil | ||
92 | } | ||
93 | |||
94 | // DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5. | ||
95 | @@ -150,7 +149,7 @@ func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid | ||
96 | return | ||
97 | } | ||
98 | |||
99 | - em = leftPad(m.Bytes(), k) | ||
100 | + em = m.FillBytes(make([]byte, k)) | ||
101 | firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0) | ||
102 | secondByteIsTwo := subtle.ConstantTimeByteEq(em[1], 2) | ||
103 | |||
104 | @@ -256,8 +255,7 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []b | ||
105 | return nil, err | ||
106 | } | ||
107 | |||
108 | - copyWithLeftPad(em, c.Bytes()) | ||
109 | - return em, nil | ||
110 | + return c.FillBytes(em), nil | ||
111 | } | ||
112 | |||
113 | // VerifyPKCS1v15 verifies an RSA PKCS#1 v1.5 signature. | ||
114 | @@ -286,7 +284,7 @@ func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) | ||
115 | |||
116 | c := new(big.Int).SetBytes(sig) | ||
117 | m := encrypt(new(big.Int), pub, c) | ||
118 | - em := leftPad(m.Bytes(), k) | ||
119 | + em := m.FillBytes(make([]byte, k)) | ||
120 | // EM = 0x00 || 0x01 || PS || 0x00 || T | ||
121 | |||
122 | ok := subtle.ConstantTimeByteEq(em[0], 0) | ||
123 | @@ -323,13 +321,3 @@ func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte, | ||
124 | } | ||
125 | return | ||
126 | } | ||
127 | - | ||
128 | -// copyWithLeftPad copies src to the end of dest, padding with zero bytes as | ||
129 | -// needed. | ||
130 | -func copyWithLeftPad(dest, src []byte) { | ||
131 | - numPaddingBytes := len(dest) - len(src) | ||
132 | - for i := 0; i < numPaddingBytes; i++ { | ||
133 | - dest[i] = 0 | ||
134 | - } | ||
135 | - copy(dest[numPaddingBytes:], src) | ||
136 | -} | ||
137 | diff --git a/src/crypto/rsa/pss.go b/src/crypto/rsa/pss.go | ||
138 | index f9844d87329a8..b2adbedb28fa8 100644 | ||
139 | --- a/src/crypto/rsa/pss.go | ||
140 | +++ b/src/crypto/rsa/pss.go | ||
141 | @@ -207,20 +207,19 @@ func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error { | ||
142 | // Note that hashed must be the result of hashing the input message using the | ||
143 | // given hash function. salt is a random sequence of bytes whose length will be | ||
144 | // later used to verify the signature. | ||
145 | -func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) (s []byte, err error) { | ||
146 | +func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) ([]byte, error) { | ||
147 | emBits := priv.N.BitLen() - 1 | ||
148 | em, err := emsaPSSEncode(hashed, emBits, salt, hash.New()) | ||
149 | if err != nil { | ||
150 | - return | ||
151 | + return nil, err | ||
152 | } | ||
153 | m := new(big.Int).SetBytes(em) | ||
154 | c, err := decryptAndCheck(rand, priv, m) | ||
155 | if err != nil { | ||
156 | - return | ||
157 | + return nil, err | ||
158 | } | ||
159 | - s = make([]byte, priv.Size()) | ||
160 | - copyWithLeftPad(s, c.Bytes()) | ||
161 | - return | ||
162 | + s := make([]byte, priv.Size()) | ||
163 | + return c.FillBytes(s), nil | ||
164 | } | ||
165 | |||
166 | const ( | ||
167 | @@ -296,11 +295,9 @@ func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts | ||
168 | m := encrypt(new(big.Int), pub, s) | ||
169 | emBits := pub.N.BitLen() - 1 | ||
170 | emLen := (emBits + 7) / 8 | ||
171 | - emBytes := m.Bytes() | ||
172 | - if emLen < len(emBytes) { | ||
173 | + if m.BitLen() > emLen*8 { | ||
174 | return ErrVerification | ||
175 | } | ||
176 | - em := make([]byte, emLen) | ||
177 | - copyWithLeftPad(em, emBytes) | ||
178 | + em := m.FillBytes(make([]byte, emLen)) | ||
179 | return emsaPSSVerify(digest, em, emBits, opts.saltLength(), hash.New()) | ||
180 | } | ||
181 | diff --git a/src/crypto/rsa/rsa.go b/src/crypto/rsa/rsa.go | ||
182 | index b4bfa13defbdf..28eb5926c1a54 100644 | ||
183 | --- a/src/crypto/rsa/rsa.go | ||
184 | +++ b/src/crypto/rsa/rsa.go | ||
185 | @@ -416,16 +416,9 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l | ||
186 | m := new(big.Int) | ||
187 | m.SetBytes(em) | ||
188 | c := encrypt(new(big.Int), pub, m) | ||
189 | - out := c.Bytes() | ||
190 | |||
191 | - if len(out) < k { | ||
192 | - // If the output is too small, we need to left-pad with zeros. | ||
193 | - t := make([]byte, k) | ||
194 | - copy(t[k-len(out):], out) | ||
195 | - out = t | ||
196 | - } | ||
197 | - | ||
198 | - return out, nil | ||
199 | + out := make([]byte, k) | ||
200 | + return c.FillBytes(out), nil | ||
201 | } | ||
202 | |||
203 | // ErrDecryption represents a failure to decrypt a message. | ||
204 | @@ -597,12 +590,9 @@ func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext | ||
205 | lHash := hash.Sum(nil) | ||
206 | hash.Reset() | ||
207 | |||
208 | - // Converting the plaintext number to bytes will strip any | ||
209 | - // leading zeros so we may have to left pad. We do this unconditionally | ||
210 | - // to avoid leaking timing information. (Although we still probably | ||
211 | - // leak the number of leading zeros. It's not clear that we can do | ||
212 | - // anything about this.) | ||
213 | - em := leftPad(m.Bytes(), k) | ||
214 | + // We probably leak the number of leading zeros. | ||
215 | + // It's not clear that we can do anything about this. | ||
216 | + em := m.FillBytes(make([]byte, k)) | ||
217 | |||
218 | firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0) | ||
219 | |||
220 | @@ -643,15 +633,3 @@ func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext | ||
221 | |||
222 | return rest[index+1:], nil | ||
223 | } | ||
224 | - | ||
225 | -// leftPad returns a new slice of length size. The contents of input are right | ||
226 | -// aligned in the new slice. | ||
227 | -func leftPad(input []byte, size int) (out []byte) { | ||
228 | - n := len(input) | ||
229 | - if n > size { | ||
230 | - n = size | ||
231 | - } | ||
232 | - out = make([]byte, size) | ||
233 | - copy(out[len(out)-n:], input) | ||
234 | - return | ||
235 | -} | ||
236 | diff --git a/src/crypto/tls/key_schedule.go b/src/crypto/tls/key_schedule.go | ||
237 | index 2aab323202f7d..314016979afb8 100644 | ||
238 | --- a/src/crypto/tls/key_schedule.go | ||
239 | +++ b/src/crypto/tls/key_schedule.go | ||
240 | @@ -173,11 +173,8 @@ func (p *nistParameters) SharedKey(peerPublicKey []byte) []byte { | ||
241 | } | ||
242 | |||
243 | xShared, _ := curve.ScalarMult(x, y, p.privateKey) | ||
244 | - sharedKey := make([]byte, (curve.Params().BitSize+7)>>3) | ||
245 | - xBytes := xShared.Bytes() | ||
246 | - copy(sharedKey[len(sharedKey)-len(xBytes):], xBytes) | ||
247 | - | ||
248 | - return sharedKey | ||
249 | + sharedKey := make([]byte, (curve.Params().BitSize+7)/8) | ||
250 | + return xShared.FillBytes(sharedKey) | ||
251 | } | ||
252 | |||
253 | type x25519Parameters struct { | ||
254 | diff --git a/src/crypto/x509/sec1.go b/src/crypto/x509/sec1.go | ||
255 | index 0bfb90cd5464a..52c108ff1d624 100644 | ||
256 | --- a/src/crypto/x509/sec1.go | ||
257 | +++ b/src/crypto/x509/sec1.go | ||
258 | @@ -52,13 +52,10 @@ func MarshalECPrivateKey(key *ecdsa.PrivateKey) ([]byte, error) { | ||
259 | // marshalECPrivateKey marshals an EC private key into ASN.1, DER format and | ||
260 | // sets the curve ID to the given OID, or omits it if OID is nil. | ||
261 | func marshalECPrivateKeyWithOID(key *ecdsa.PrivateKey, oid asn1.ObjectIdentifier) ([]byte, error) { | ||
262 | - privateKeyBytes := key.D.Bytes() | ||
263 | - paddedPrivateKey := make([]byte, (key.Curve.Params().N.BitLen()+7)/8) | ||
264 | - copy(paddedPrivateKey[len(paddedPrivateKey)-len(privateKeyBytes):], privateKeyBytes) | ||
265 | - | ||
266 | + privateKey := make([]byte, (key.Curve.Params().N.BitLen()+7)/8) | ||
267 | return asn1.Marshal(ecPrivateKey{ | ||
268 | Version: 1, | ||
269 | - PrivateKey: paddedPrivateKey, | ||
270 | + PrivateKey: key.D.FillBytes(privateKey), | ||
271 | NamedCurveOID: oid, | ||
272 | PublicKey: asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)}, | ||
273 | }) | ||
274 | diff --git a/src/math/big/int.go b/src/math/big/int.go | ||
275 | index 8816cf5266cc4..65f32487b58c0 100644 | ||
276 | --- a/src/math/big/int.go | ||
277 | +++ b/src/math/big/int.go | ||
278 | @@ -447,11 +447,26 @@ func (z *Int) SetBytes(buf []byte) *Int { | ||
279 | } | ||
280 | |||
281 | // Bytes returns the absolute value of x as a big-endian byte slice. | ||
282 | +// | ||
283 | +// To use a fixed length slice, or a preallocated one, use FillBytes. | ||
284 | func (x *Int) Bytes() []byte { | ||
285 | buf := make([]byte, len(x.abs)*_S) | ||
286 | return buf[x.abs.bytes(buf):] | ||
287 | } | ||
288 | |||
289 | +// FillBytes sets buf to the absolute value of x, storing it as a zero-extended | ||
290 | +// big-endian byte slice, and returns buf. | ||
291 | +// | ||
292 | +// If the absolute value of x doesn't fit in buf, FillBytes will panic. | ||
293 | +func (x *Int) FillBytes(buf []byte) []byte { | ||
294 | + // Clear whole buffer. (This gets optimized into a memclr.) | ||
295 | + for i := range buf { | ||
296 | + buf[i] = 0 | ||
297 | + } | ||
298 | + x.abs.bytes(buf) | ||
299 | + return buf | ||
300 | +} | ||
301 | + | ||
302 | // BitLen returns the length of the absolute value of x in bits. | ||
303 | // The bit length of 0 is 0. | ||
304 | func (x *Int) BitLen() int { | ||
305 | diff --git a/src/math/big/int_test.go b/src/math/big/int_test.go | ||
306 | index e3a1587b3f0ad..3c8557323a032 100644 | ||
307 | --- a/src/math/big/int_test.go | ||
308 | +++ b/src/math/big/int_test.go | ||
309 | @@ -1840,3 +1840,57 @@ func BenchmarkDiv(b *testing.B) { | ||
310 | }) | ||
311 | } | ||
312 | } | ||
313 | + | ||
314 | +func TestFillBytes(t *testing.T) { | ||
315 | + checkResult := func(t *testing.T, buf []byte, want *Int) { | ||
316 | + t.Helper() | ||
317 | + got := new(Int).SetBytes(buf) | ||
318 | + if got.CmpAbs(want) != 0 { | ||
319 | + t.Errorf("got 0x%x, want 0x%x: %x", got, want, buf) | ||
320 | + } | ||
321 | + } | ||
322 | + panics := func(f func()) (panic bool) { | ||
323 | + defer func() { panic = recover() != nil }() | ||
324 | + f() | ||
325 | + return | ||
326 | + } | ||
327 | + | ||
328 | + for _, n := range []string{ | ||
329 | + "0", | ||
330 | + "1000", | ||
331 | + "0xffffffff", | ||
332 | + "-0xffffffff", | ||
333 | + "0xffffffffffffffff", | ||
334 | + "0x10000000000000000", | ||
335 | + "0xabababababababababababababababababababababababababa", | ||
336 | + "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", | ||
337 | + } { | ||
338 | + t.Run(n, func(t *testing.T) { | ||
339 | + t.Logf(n) | ||
340 | + x, ok := new(Int).SetString(n, 0) | ||
341 | + if !ok { | ||
342 | + panic("invalid test entry") | ||
343 | + } | ||
344 | + | ||
345 | + // Perfectly sized buffer. | ||
346 | + byteLen := (x.BitLen() + 7) / 8 | ||
347 | + buf := make([]byte, byteLen) | ||
348 | + checkResult(t, x.FillBytes(buf), x) | ||
349 | + | ||
350 | + // Way larger, checking all bytes get zeroed. | ||
351 | + buf = make([]byte, 100) | ||
352 | + for i := range buf { | ||
353 | + buf[i] = 0xff | ||
354 | + } | ||
355 | + checkResult(t, x.FillBytes(buf), x) | ||
356 | + | ||
357 | + // Too small. | ||
358 | + if byteLen > 0 { | ||
359 | + buf = make([]byte, byteLen-1) | ||
360 | + if !panics(func() { x.FillBytes(buf) }) { | ||
361 | + t.Errorf("expected panic for small buffer and value %x", x) | ||
362 | + } | ||
363 | + } | ||
364 | + }) | ||
365 | + } | ||
366 | +} | ||
367 | diff --git a/src/math/big/nat.go b/src/math/big/nat.go | ||
368 | index c31ec5156b81d..6a3989bf9d82b 100644 | ||
369 | --- a/src/math/big/nat.go | ||
370 | +++ b/src/math/big/nat.go | ||
371 | @@ -1476,19 +1476,26 @@ func (z nat) expNNMontgomery(x, y, m nat) nat { | ||
372 | } | ||
373 | |||
374 | // bytes writes the value of z into buf using big-endian encoding. | ||
375 | -// len(buf) must be >= len(z)*_S. The value of z is encoded in the | ||
376 | -// slice buf[i:]. The number i of unused bytes at the beginning of | ||
377 | -// buf is returned as result. | ||
378 | +// The value of z is encoded in the slice buf[i:]. If the value of z | ||
379 | +// cannot be represented in buf, bytes panics. The number i of unused | ||
380 | +// bytes at the beginning of buf is returned as result. | ||
381 | func (z nat) bytes(buf []byte) (i int) { | ||
382 | i = len(buf) | ||
383 | for _, d := range z { | ||
384 | for j := 0; j < _S; j++ { | ||
385 | i-- | ||
386 | - buf[i] = byte(d) | ||
387 | + if i >= 0 { | ||
388 | + buf[i] = byte(d) | ||
389 | + } else if byte(d) != 0 { | ||
390 | + panic("math/big: buffer too small to fit value") | ||
391 | + } | ||
392 | d >>= 8 | ||
393 | } | ||
394 | } | ||
395 | |||
396 | + if i < 0 { | ||
397 | + i = 0 | ||
398 | + } | ||
399 | for i < len(buf) && buf[i] == 0 { | ||
400 | i++ | ||
401 | } | ||
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-45287-pre3.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-45287-pre3.patch new file mode 100644 index 0000000000..ae9fcc170c --- /dev/null +++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-45287-pre3.patch | |||
@@ -0,0 +1,86 @@ | |||
1 | From 8f676144ad7b7c91adb0c6e1ec89aaa6283c6807 Mon Sep 17 00:00:00 2001 | ||
2 | From: Himanshu Kishna Srivastava <28himanshu@gmail.com> | ||
3 | Date: Tue, 16 Mar 2021 22:37:46 +0530 | ||
4 | Subject: [PATCH] crypto/rsa: fix salt length calculation with | ||
5 | PSSSaltLengthAuto | ||
6 | |||
7 | When PSSSaltLength is set, the maximum salt length must equal: | ||
8 | |||
9 | (modulus_key_size - 1 + 7)/8 - hash_length - 2 | ||
10 | and for example, with a 4096 bit modulus key, and a SHA-1 hash, | ||
11 | it should be: | ||
12 | |||
13 | (4096 -1 + 7)/8 - 20 - 2 = 490 | ||
14 | Previously we'd encounter this error: | ||
15 | |||
16 | crypto/rsa: key size too small for PSS signature | ||
17 | |||
18 | Fixes #42741 | ||
19 | |||
20 | Change-Id: I18bb82c41c511d564b3f4c443f4b3a38ab010ac5 | ||
21 | Reviewed-on: https://go-review.googlesource.com/c/go/+/302230 | ||
22 | Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com> | ||
23 | Reviewed-by: Filippo Valsorda <filippo@golang.org> | ||
24 | Trust: Emmanuel Odeke <emmanuel@orijtech.com> | ||
25 | Run-TryBot: Emmanuel Odeke <emmanuel@orijtech.com> | ||
26 | TryBot-Result: Go Bot <gobot@golang.org> | ||
27 | |||
28 | Upstream-Status: Backport [https://github.com/golang/go/commit/8f676144ad7b7c91adb0c6e1ec89aaa6283c6807] | ||
29 | CVE: CVE-2023-45287 #Dependency Patch3 | ||
30 | Signed-off-by: Vijay Anusuri <vanusuri@mvista.com> | ||
31 | --- | ||
32 | src/crypto/rsa/pss.go | 2 +- | ||
33 | src/crypto/rsa/pss_test.go | 20 +++++++++++++++++++- | ||
34 | 2 files changed, 20 insertions(+), 2 deletions(-) | ||
35 | |||
36 | diff --git a/src/crypto/rsa/pss.go b/src/crypto/rsa/pss.go | ||
37 | index b2adbedb28fa8..814522de8181f 100644 | ||
38 | --- a/src/crypto/rsa/pss.go | ||
39 | +++ b/src/crypto/rsa/pss.go | ||
40 | @@ -269,7 +269,7 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, | ||
41 | saltLength := opts.saltLength() | ||
42 | switch saltLength { | ||
43 | case PSSSaltLengthAuto: | ||
44 | - saltLength = priv.Size() - 2 - hash.Size() | ||
45 | + saltLength = (priv.N.BitLen()-1+7)/8 - 2 - hash.Size() | ||
46 | case PSSSaltLengthEqualsHash: | ||
47 | saltLength = hash.Size() | ||
48 | } | ||
49 | diff --git a/src/crypto/rsa/pss_test.go b/src/crypto/rsa/pss_test.go | ||
50 | index dfa8d8bb5ad02..c3a6d468497cd 100644 | ||
51 | --- a/src/crypto/rsa/pss_test.go | ||
52 | +++ b/src/crypto/rsa/pss_test.go | ||
53 | @@ -12,7 +12,7 @@ import ( | ||
54 | _ "crypto/md5" | ||
55 | "crypto/rand" | ||
56 | "crypto/sha1" | ||
57 | - _ "crypto/sha256" | ||
58 | + "crypto/sha256" | ||
59 | "encoding/hex" | ||
60 | "math/big" | ||
61 | "os" | ||
62 | @@ -233,6 +233,24 @@ func TestPSSSigning(t *testing.T) { | ||
63 | } | ||
64 | } | ||
65 | |||
66 | +func TestSignWithPSSSaltLengthAuto(t *testing.T) { | ||
67 | + key, err := GenerateKey(rand.Reader, 513) | ||
68 | + if err != nil { | ||
69 | + t.Fatal(err) | ||
70 | + } | ||
71 | + digest := sha256.Sum256([]byte("message")) | ||
72 | + signature, err := key.Sign(rand.Reader, digest[:], &PSSOptions{ | ||
73 | + SaltLength: PSSSaltLengthAuto, | ||
74 | + Hash: crypto.SHA256, | ||
75 | + }) | ||
76 | + if err != nil { | ||
77 | + t.Fatal(err) | ||
78 | + } | ||
79 | + if len(signature) == 0 { | ||
80 | + t.Fatal("empty signature returned") | ||
81 | + } | ||
82 | +} | ||
83 | + | ||
84 | func bigFromHex(hex string) *big.Int { | ||
85 | n, ok := new(big.Int).SetString(hex, 16) | ||
86 | if !ok { | ||
diff --git a/meta/recipes-devtools/go/go-1.14/CVE-2023-45287.patch b/meta/recipes-devtools/go/go-1.14/CVE-2023-45287.patch new file mode 100644 index 0000000000..90a74255db --- /dev/null +++ b/meta/recipes-devtools/go/go-1.14/CVE-2023-45287.patch | |||
@@ -0,0 +1,1697 @@ | |||
1 | From 8a81fdf165facdcefa06531de5af98a4db343035 Mon Sep 17 00:00:00 2001 | ||
2 | From: =?UTF-8?q?L=C3=BAc=C3=A1s=20Meier?= <cronokirby@gmail.com> | ||
3 | Date: Tue, 8 Jun 2021 21:36:06 +0200 | ||
4 | Subject: [PATCH] crypto/rsa: replace big.Int for encryption and decryption | ||
5 | |||
6 | Infamously, big.Int does not provide constant-time arithmetic, making | ||
7 | its use in cryptographic code quite tricky. RSA uses big.Int | ||
8 | pervasively, in its public API, for key generation, precomputation, and | ||
9 | for encryption and decryption. This is a known problem. One mitigation, | ||
10 | blinding, is already in place during decryption. This helps mitigate the | ||
11 | very leaky exponentiation operation. Because big.Int is fundamentally | ||
12 | not constant-time, it's unfortunately difficult to guarantee that | ||
13 | mitigations like these are completely effective. | ||
14 | |||
15 | This patch removes the use of big.Int for encryption and decryption, | ||
16 | replacing it with an internal nat type instead. Signing and verification | ||
17 | are also affected, because they depend on encryption and decryption. | ||
18 | |||
19 | Overall, this patch degrades performance by 55% for private key | ||
20 | operations, and 4-5x for (much faster) public key operations. | ||
21 | (Signatures do both, so the slowdown is worse than decryption.) | ||
22 | |||
23 | name old time/op new time/op delta | ||
24 | DecryptPKCS1v15/2048-8 1.50ms ± 0% 2.34ms ± 0% +56.44% (p=0.000 n=8+10) | ||
25 | DecryptPKCS1v15/3072-8 4.40ms ± 0% 6.79ms ± 0% +54.33% (p=0.000 n=10+9) | ||
26 | DecryptPKCS1v15/4096-8 9.31ms ± 0% 15.14ms ± 0% +62.60% (p=0.000 n=10+10) | ||
27 | EncryptPKCS1v15/2048-8 8.16µs ± 0% 355.58µs ± 0% +4258.90% (p=0.000 n=10+9) | ||
28 | DecryptOAEP/2048-8 1.50ms ± 0% 2.34ms ± 0% +55.68% (p=0.000 n=10+9) | ||
29 | EncryptOAEP/2048-8 8.51µs ± 0% 355.95µs ± 0% +4082.75% (p=0.000 n=10+9) | ||
30 | SignPKCS1v15/2048-8 1.51ms ± 0% 2.69ms ± 0% +77.94% (p=0.000 n=10+10) | ||
31 | VerifyPKCS1v15/2048-8 7.25µs ± 0% 354.34µs ± 0% +4789.52% (p=0.000 n=9+9) | ||
32 | SignPSS/2048-8 1.51ms ± 0% 2.70ms ± 0% +78.80% (p=0.000 n=9+10) | ||
33 | VerifyPSS/2048-8 8.27µs ± 1% 355.65µs ± 0% +4199.39% (p=0.000 n=10+10) | ||
34 | |||
35 | Keep in mind that this is without any assembly at all, and that further | ||
36 | improvements are likely possible. I think having a review of the logic | ||
37 | and the cryptography would be a good idea at this stage, before we | ||
38 | complicate the code too much through optimization. | ||
39 | |||
40 | The bulk of the work is in nat.go. This introduces two new types: nat, | ||
41 | representing natural numbers, and modulus, representing moduli used in | ||
42 | modular arithmetic. | ||
43 | |||
44 | A nat has an "announced size", which may be larger than its "true size", | ||
45 | the number of bits needed to represent this number. Operations on a nat | ||
46 | will only ever leak its announced size, never its true size, or other | ||
47 | information about its value. The size of a nat is always clear based on | ||
48 | how its value is set. For example, x.mod(y, m) will make the announced | ||
49 | size of x match that of m, since x is reduced modulo m. | ||
50 | |||
51 | Operations assume that the announced size of the operands match what's | ||
52 | expected (with a few exceptions). For example, x.modAdd(y, m) assumes | ||
53 | that x and y have the same announced size as m, and that they're reduced | ||
54 | modulo m. | ||
55 | |||
56 | Nats are represented over unsatured bits.UintSize - 1 bit limbs. This | ||
57 | means that we can't reuse the assembly routines for big.Int, which use | ||
58 | saturated bits.UintSize limbs. The advantage of unsaturated limbs is | ||
59 | that it makes Montgomery multiplication faster, by needing fewer | ||
60 | registers in a hot loop. This makes exponentiation faster, which | ||
61 | consists of many Montgomery multiplications. | ||
62 | |||
63 | Moduli use nat internally. Unlike nat, the true size of a modulus always | ||
64 | matches its announced size. When creating a modulus, any zero padding is | ||
65 | removed. Moduli will also precompute constants when created, which is | ||
66 | another reason why having a separate type is desirable. | ||
67 | |||
68 | Updates #20654 | ||
69 | |||
70 | Co-authored-by: Filippo Valsorda <filippo@golang.org> | ||
71 | Change-Id: I73b61f87d58ab912e80a9644e255d552cbadcced | ||
72 | Reviewed-on: https://go-review.googlesource.com/c/go/+/326012 | ||
73 | Run-TryBot: Filippo Valsorda <filippo@golang.org> | ||
74 | TryBot-Result: Gopher Robot <gobot@golang.org> | ||
75 | Reviewed-by: Roland Shoemaker <roland@golang.org> | ||
76 | Reviewed-by: Joedian Reid <joedian@golang.org> | ||
77 | |||
78 | Upstream-Status: Backport [https://github.com/golang/go/commit/8a81fdf165facdcefa06531de5af98a4db343035] | ||
79 | CVE: CVE-2023-45287 | ||
80 | Signed-off-by: Vijay Anusuri <vanusuri@mvista.com> | ||
81 | --- | ||
82 | src/crypto/rsa/example_test.go | 21 +- | ||
83 | src/crypto/rsa/nat.go | 626 +++++++++++++++++++++++++++++++++ | ||
84 | src/crypto/rsa/nat_test.go | 384 ++++++++++++++++++++ | ||
85 | src/crypto/rsa/pkcs1v15.go | 47 +-- | ||
86 | src/crypto/rsa/pss.go | 50 ++- | ||
87 | src/crypto/rsa/pss_test.go | 10 +- | ||
88 | src/crypto/rsa/rsa.go | 174 ++++----- | ||
89 | 7 files changed, 1143 insertions(+), 169 deletions(-) | ||
90 | create mode 100644 src/crypto/rsa/nat.go | ||
91 | create mode 100644 src/crypto/rsa/nat_test.go | ||
92 | |||
93 | diff --git a/src/crypto/rsa/example_test.go b/src/crypto/rsa/example_test.go | ||
94 | index 1435b70..1963609 100644 | ||
95 | --- a/src/crypto/rsa/example_test.go | ||
96 | +++ b/src/crypto/rsa/example_test.go | ||
97 | @@ -12,7 +12,6 @@ import ( | ||
98 | "crypto/sha256" | ||
99 | "encoding/hex" | ||
100 | "fmt" | ||
101 | - "io" | ||
102 | "os" | ||
103 | ) | ||
104 | |||
105 | @@ -36,21 +35,17 @@ import ( | ||
106 | // a buffer that contains a random key. Thus, if the RSA result isn't | ||
107 | // well-formed, the implementation uses a random key in constant time. | ||
108 | func ExampleDecryptPKCS1v15SessionKey() { | ||
109 | - // crypto/rand.Reader is a good source of entropy for blinding the RSA | ||
110 | - // operation. | ||
111 | - rng := rand.Reader | ||
112 | - | ||
113 | // The hybrid scheme should use at least a 16-byte symmetric key. Here | ||
114 | // we read the random key that will be used if the RSA decryption isn't | ||
115 | // well-formed. | ||
116 | key := make([]byte, 32) | ||
117 | - if _, err := io.ReadFull(rng, key); err != nil { | ||
118 | + if _, err := rand.Read(key); err != nil { | ||
119 | panic("RNG failure") | ||
120 | } | ||
121 | |||
122 | rsaCiphertext, _ := hex.DecodeString("aabbccddeeff") | ||
123 | |||
124 | - if err := DecryptPKCS1v15SessionKey(rng, rsaPrivateKey, rsaCiphertext, key); err != nil { | ||
125 | + if err := DecryptPKCS1v15SessionKey(nil, rsaPrivateKey, rsaCiphertext, key); err != nil { | ||
126 | // Any errors that result will be “public” – meaning that they | ||
127 | // can be determined without any secret information. (For | ||
128 | // instance, if the length of key is impossible given the RSA | ||
129 | @@ -86,10 +81,6 @@ func ExampleDecryptPKCS1v15SessionKey() { | ||
130 | } | ||
131 | |||
132 | func ExampleSignPKCS1v15() { | ||
133 | - // crypto/rand.Reader is a good source of entropy for blinding the RSA | ||
134 | - // operation. | ||
135 | - rng := rand.Reader | ||
136 | - | ||
137 | message := []byte("message to be signed") | ||
138 | |||
139 | // Only small messages can be signed directly; thus the hash of a | ||
140 | @@ -99,7 +90,7 @@ func ExampleSignPKCS1v15() { | ||
141 | // of writing (2016). | ||
142 | hashed := sha256.Sum256(message) | ||
143 | |||
144 | - signature, err := SignPKCS1v15(rng, rsaPrivateKey, crypto.SHA256, hashed[:]) | ||
145 | + signature, err := SignPKCS1v15(nil, rsaPrivateKey, crypto.SHA256, hashed[:]) | ||
146 | if err != nil { | ||
147 | fmt.Fprintf(os.Stderr, "Error from signing: %s\n", err) | ||
148 | return | ||
149 | @@ -151,11 +142,7 @@ func ExampleDecryptOAEP() { | ||
150 | ciphertext, _ := hex.DecodeString("4d1ee10e8f286390258c51a5e80802844c3e6358ad6690b7285218a7c7ed7fc3a4c7b950fbd04d4b0239cc060dcc7065ca6f84c1756deb71ca5685cadbb82be025e16449b905c568a19c088a1abfad54bf7ecc67a7df39943ec511091a34c0f2348d04e058fcff4d55644de3cd1d580791d4524b92f3e91695582e6e340a1c50b6c6d78e80b4e42c5b4d45e479b492de42bbd39cc642ebb80226bb5200020d501b24a37bcc2ec7f34e596b4fd6b063de4858dbf5a4e3dd18e262eda0ec2d19dbd8e890d672b63d368768360b20c0b6b8592a438fa275e5fa7f60bef0dd39673fd3989cc54d2cb80c08fcd19dacbc265ee1c6014616b0e04ea0328c2a04e73460") | ||
151 | label := []byte("orders") | ||
152 | |||
153 | - // crypto/rand.Reader is a good source of entropy for blinding the RSA | ||
154 | - // operation. | ||
155 | - rng := rand.Reader | ||
156 | - | ||
157 | - plaintext, err := DecryptOAEP(sha256.New(), rng, test2048Key, ciphertext, label) | ||
158 | + plaintext, err := DecryptOAEP(sha256.New(), nil, test2048Key, ciphertext, label) | ||
159 | if err != nil { | ||
160 | fmt.Fprintf(os.Stderr, "Error from decryption: %s\n", err) | ||
161 | return | ||
162 | diff --git a/src/crypto/rsa/nat.go b/src/crypto/rsa/nat.go | ||
163 | new file mode 100644 | ||
164 | index 0000000..da521c2 | ||
165 | --- /dev/null | ||
166 | +++ b/src/crypto/rsa/nat.go | ||
167 | @@ -0,0 +1,626 @@ | ||
168 | +// Copyright 2021 The Go Authors. All rights reserved. | ||
169 | +// Use of this source code is governed by a BSD-style | ||
170 | +// license that can be found in the LICENSE file. | ||
171 | + | ||
172 | +package rsa | ||
173 | + | ||
174 | +import ( | ||
175 | + "math/big" | ||
176 | + "math/bits" | ||
177 | +) | ||
178 | + | ||
179 | +const ( | ||
180 | + // _W is the number of bits we use for our limbs. | ||
181 | + _W = bits.UintSize - 1 | ||
182 | + // _MASK selects _W bits from a full machine word. | ||
183 | + _MASK = (1 << _W) - 1 | ||
184 | +) | ||
185 | + | ||
186 | +// choice represents a constant-time boolean. The value of choice is always | ||
187 | +// either 1 or 0. We use an int instead of bool in order to make decisions in | ||
188 | +// constant time by turning it into a mask. | ||
189 | +type choice uint | ||
190 | + | ||
191 | +func not(c choice) choice { return 1 ^ c } | ||
192 | + | ||
193 | +const yes = choice(1) | ||
194 | +const no = choice(0) | ||
195 | + | ||
196 | +// ctSelect returns x if on == 1, and y if on == 0. The execution time of this | ||
197 | +// function does not depend on its inputs. If on is any value besides 1 or 0, | ||
198 | +// the result is undefined. | ||
199 | +func ctSelect(on choice, x, y uint) uint { | ||
200 | + // When on == 1, mask is 0b111..., otherwise mask is 0b000... | ||
201 | + mask := -uint(on) | ||
202 | + // When mask is all zeros, we just have y, otherwise, y cancels with itself. | ||
203 | + return y ^ (mask & (y ^ x)) | ||
204 | +} | ||
205 | + | ||
206 | +// ctEq returns 1 if x == y, and 0 otherwise. The execution time of this | ||
207 | +// function does not depend on its inputs. | ||
208 | +func ctEq(x, y uint) choice { | ||
209 | + // If x != y, then either x - y or y - x will generate a carry. | ||
210 | + _, c1 := bits.Sub(x, y, 0) | ||
211 | + _, c2 := bits.Sub(y, x, 0) | ||
212 | + return not(choice(c1 | c2)) | ||
213 | +} | ||
214 | + | ||
215 | +// ctGeq returns 1 if x >= y, and 0 otherwise. The execution time of this | ||
216 | +// function does not depend on its inputs. | ||
217 | +func ctGeq(x, y uint) choice { | ||
218 | + // If x < y, then x - y generates a carry. | ||
219 | + _, carry := bits.Sub(x, y, 0) | ||
220 | + return not(choice(carry)) | ||
221 | +} | ||
222 | + | ||
223 | +// nat represents an arbitrary natural number | ||
224 | +// | ||
225 | +// Each nat has an announced length, which is the number of limbs it has stored. | ||
226 | +// Operations on this number are allowed to leak this length, but will not leak | ||
227 | +// any information about the values contained in those limbs. | ||
228 | +type nat struct { | ||
229 | + // limbs is a little-endian representation in base 2^W with | ||
230 | + // W = bits.UintSize - 1. The top bit is always unset between operations. | ||
231 | + // | ||
232 | + // The top bit is left unset to optimize Montgomery multiplication, in the | ||
233 | + // inner loop of exponentiation. Using fully saturated limbs would leave us | ||
234 | + // working with 129-bit numbers on 64-bit platforms, wasting a lot of space, | ||
235 | + // and thus time. | ||
236 | + limbs []uint | ||
237 | +} | ||
238 | + | ||
239 | +// expand expands x to n limbs, leaving its value unchanged. | ||
240 | +func (x *nat) expand(n int) *nat { | ||
241 | + for len(x.limbs) > n { | ||
242 | + if x.limbs[len(x.limbs)-1] != 0 { | ||
243 | + panic("rsa: internal error: shrinking nat") | ||
244 | + } | ||
245 | + x.limbs = x.limbs[:len(x.limbs)-1] | ||
246 | + } | ||
247 | + if cap(x.limbs) < n { | ||
248 | + newLimbs := make([]uint, n) | ||
249 | + copy(newLimbs, x.limbs) | ||
250 | + x.limbs = newLimbs | ||
251 | + return x | ||
252 | + } | ||
253 | + extraLimbs := x.limbs[len(x.limbs):n] | ||
254 | + for i := range extraLimbs { | ||
255 | + extraLimbs[i] = 0 | ||
256 | + } | ||
257 | + x.limbs = x.limbs[:n] | ||
258 | + return x | ||
259 | +} | ||
260 | + | ||
261 | +// reset returns a zero nat of n limbs, reusing x's storage if n <= cap(x.limbs). | ||
262 | +func (x *nat) reset(n int) *nat { | ||
263 | + if cap(x.limbs) < n { | ||
264 | + x.limbs = make([]uint, n) | ||
265 | + return x | ||
266 | + } | ||
267 | + for i := range x.limbs { | ||
268 | + x.limbs[i] = 0 | ||
269 | + } | ||
270 | + x.limbs = x.limbs[:n] | ||
271 | + return x | ||
272 | +} | ||
273 | + | ||
274 | +// clone returns a new nat, with the same value and announced length as x. | ||
275 | +func (x *nat) clone() *nat { | ||
276 | + out := &nat{make([]uint, len(x.limbs))} | ||
277 | + copy(out.limbs, x.limbs) | ||
278 | + return out | ||
279 | +} | ||
280 | + | ||
281 | +// natFromBig creates a new natural number from a big.Int. | ||
282 | +// | ||
283 | +// The announced length of the resulting nat is based on the actual bit size of | ||
284 | +// the input, ignoring leading zeroes. | ||
285 | +func natFromBig(x *big.Int) *nat { | ||
286 | + xLimbs := x.Bits() | ||
287 | + bitSize := bigBitLen(x) | ||
288 | + requiredLimbs := (bitSize + _W - 1) / _W | ||
289 | + | ||
290 | + out := &nat{make([]uint, requiredLimbs)} | ||
291 | + outI := 0 | ||
292 | + shift := 0 | ||
293 | + for i := range xLimbs { | ||
294 | + xi := uint(xLimbs[i]) | ||
295 | + out.limbs[outI] |= (xi << shift) & _MASK | ||
296 | + outI++ | ||
297 | + if outI == requiredLimbs { | ||
298 | + return out | ||
299 | + } | ||
300 | + out.limbs[outI] = xi >> (_W - shift) | ||
301 | + shift++ // this assumes bits.UintSize - _W = 1 | ||
302 | + if shift == _W { | ||
303 | + shift = 0 | ||
304 | + outI++ | ||
305 | + } | ||
306 | + } | ||
307 | + return out | ||
308 | +} | ||
309 | + | ||
310 | +// fillBytes sets bytes to x as a zero-extended big-endian byte slice. | ||
311 | +// | ||
312 | +// If bytes is not long enough to contain the number or at least len(x.limbs)-1 | ||
313 | +// limbs, or has zero length, fillBytes will panic. | ||
314 | +func (x *nat) fillBytes(bytes []byte) []byte { | ||
315 | + if len(bytes) == 0 { | ||
316 | + panic("nat: fillBytes invoked with too small buffer") | ||
317 | + } | ||
318 | + for i := range bytes { | ||
319 | + bytes[i] = 0 | ||
320 | + } | ||
321 | + shift := 0 | ||
322 | + outI := len(bytes) - 1 | ||
323 | + for i, limb := range x.limbs { | ||
324 | + remainingBits := _W | ||
325 | + for remainingBits >= 8 { | ||
326 | + bytes[outI] |= byte(limb) << shift | ||
327 | + consumed := 8 - shift | ||
328 | + limb >>= consumed | ||
329 | + remainingBits -= consumed | ||
330 | + shift = 0 | ||
331 | + outI-- | ||
332 | + if outI < 0 { | ||
333 | + if limb != 0 || i < len(x.limbs)-1 { | ||
334 | + panic("nat: fillBytes invoked with too small buffer") | ||
335 | + } | ||
336 | + return bytes | ||
337 | + } | ||
338 | + } | ||
339 | + bytes[outI] = byte(limb) | ||
340 | + shift = remainingBits | ||
341 | + } | ||
342 | + return bytes | ||
343 | +} | ||
344 | + | ||
345 | +// natFromBytes converts a slice of big-endian bytes into a nat. | ||
346 | +// | ||
347 | +// The announced length of the output depends on the length of bytes. Unlike | ||
348 | +// big.Int, creating a nat will not remove leading zeros. | ||
349 | +func natFromBytes(bytes []byte) *nat { | ||
350 | + bitSize := len(bytes) * 8 | ||
351 | + requiredLimbs := (bitSize + _W - 1) / _W | ||
352 | + | ||
353 | + out := &nat{make([]uint, requiredLimbs)} | ||
354 | + outI := 0 | ||
355 | + shift := 0 | ||
356 | + for i := len(bytes) - 1; i >= 0; i-- { | ||
357 | + bi := bytes[i] | ||
358 | + out.limbs[outI] |= uint(bi) << shift | ||
359 | + shift += 8 | ||
360 | + if shift >= _W { | ||
361 | + shift -= _W | ||
362 | + out.limbs[outI] &= _MASK | ||
363 | + outI++ | ||
364 | + if shift > 0 { | ||
365 | + out.limbs[outI] = uint(bi) >> (8 - shift) | ||
366 | + } | ||
367 | + } | ||
368 | + } | ||
369 | + return out | ||
370 | +} | ||
371 | + | ||
372 | +// cmpEq returns 1 if x == y, and 0 otherwise. | ||
373 | +// | ||
374 | +// Both operands must have the same announced length. | ||
375 | +func (x *nat) cmpEq(y *nat) choice { | ||
376 | + // Eliminate bounds checks in the loop. | ||
377 | + size := len(x.limbs) | ||
378 | + xLimbs := x.limbs[:size] | ||
379 | + yLimbs := y.limbs[:size] | ||
380 | + | ||
381 | + equal := yes | ||
382 | + for i := 0; i < size; i++ { | ||
383 | + equal &= ctEq(xLimbs[i], yLimbs[i]) | ||
384 | + } | ||
385 | + return equal | ||
386 | +} | ||
387 | + | ||
388 | +// cmpGeq returns 1 if x >= y, and 0 otherwise. | ||
389 | +// | ||
390 | +// Both operands must have the same announced length. | ||
391 | +func (x *nat) cmpGeq(y *nat) choice { | ||
392 | + // Eliminate bounds checks in the loop. | ||
393 | + size := len(x.limbs) | ||
394 | + xLimbs := x.limbs[:size] | ||
395 | + yLimbs := y.limbs[:size] | ||
396 | + | ||
397 | + var c uint | ||
398 | + for i := 0; i < size; i++ { | ||
399 | + c = (xLimbs[i] - yLimbs[i] - c) >> _W | ||
400 | + } | ||
401 | + // If there was a carry, then subtracting y underflowed, so | ||
402 | + // x is not greater than or equal to y. | ||
403 | + return not(choice(c)) | ||
404 | +} | ||
405 | + | ||
406 | +// assign sets x <- y if on == 1, and does nothing otherwise. | ||
407 | +// | ||
408 | +// Both operands must have the same announced length. | ||
409 | +func (x *nat) assign(on choice, y *nat) *nat { | ||
410 | + // Eliminate bounds checks in the loop. | ||
411 | + size := len(x.limbs) | ||
412 | + xLimbs := x.limbs[:size] | ||
413 | + yLimbs := y.limbs[:size] | ||
414 | + | ||
415 | + for i := 0; i < size; i++ { | ||
416 | + xLimbs[i] = ctSelect(on, yLimbs[i], xLimbs[i]) | ||
417 | + } | ||
418 | + return x | ||
419 | +} | ||
420 | + | ||
421 | +// add computes x += y if on == 1, and does nothing otherwise. It returns the | ||
422 | +// carry of the addition regardless of on. | ||
423 | +// | ||
424 | +// Both operands must have the same announced length. | ||
425 | +func (x *nat) add(on choice, y *nat) (c uint) { | ||
426 | + // Eliminate bounds checks in the loop. | ||
427 | + size := len(x.limbs) | ||
428 | + xLimbs := x.limbs[:size] | ||
429 | + yLimbs := y.limbs[:size] | ||
430 | + | ||
431 | + for i := 0; i < size; i++ { | ||
432 | + res := xLimbs[i] + yLimbs[i] + c | ||
433 | + xLimbs[i] = ctSelect(on, res&_MASK, xLimbs[i]) | ||
434 | + c = res >> _W | ||
435 | + } | ||
436 | + return | ||
437 | +} | ||
438 | + | ||
439 | +// sub computes x -= y if on == 1, and does nothing otherwise. It returns the | ||
440 | +// borrow of the subtraction regardless of on. | ||
441 | +// | ||
442 | +// Both operands must have the same announced length. | ||
443 | +func (x *nat) sub(on choice, y *nat) (c uint) { | ||
444 | + // Eliminate bounds checks in the loop. | ||
445 | + size := len(x.limbs) | ||
446 | + xLimbs := x.limbs[:size] | ||
447 | + yLimbs := y.limbs[:size] | ||
448 | + | ||
449 | + for i := 0; i < size; i++ { | ||
450 | + res := xLimbs[i] - yLimbs[i] - c | ||
451 | + xLimbs[i] = ctSelect(on, res&_MASK, xLimbs[i]) | ||
452 | + c = res >> _W | ||
453 | + } | ||
454 | + return | ||
455 | +} | ||
456 | + | ||
457 | +// modulus is used for modular arithmetic, precomputing relevant constants. | ||
458 | +// | ||
459 | +// Moduli are assumed to be odd numbers. Moduli can also leak the exact | ||
460 | +// number of bits needed to store their value, and are stored without padding. | ||
461 | +// | ||
462 | +// Their actual value is still kept secret. | ||
463 | +type modulus struct { | ||
464 | + // The underlying natural number for this modulus. | ||
465 | + // | ||
466 | + // This will be stored without any padding, and shouldn't alias with any | ||
467 | + // other natural number being used. | ||
468 | + nat *nat | ||
469 | + leading int // number of leading zeros in the modulus | ||
470 | + m0inv uint // -nat.limbs[0]⁻¹ mod _W | ||
471 | +} | ||
472 | + | ||
473 | +// minusInverseModW computes -x⁻¹ mod _W with x odd. | ||
474 | +// | ||
475 | +// This operation is used to precompute a constant involved in Montgomery | ||
476 | +// multiplication. | ||
477 | +func minusInverseModW(x uint) uint { | ||
478 | + // Every iteration of this loop doubles the least-significant bits of | ||
479 | + // correct inverse in y. The first three bits are already correct (1⁻¹ = 1, | ||
480 | + // 3⁻¹ = 3, 5⁻¹ = 5, and 7⁻¹ = 7 mod 8), so doubling five times is enough | ||
481 | + // for 61 bits (and wastes only one iteration for 31 bits). | ||
482 | + // | ||
483 | + // See https://crypto.stackexchange.com/a/47496. | ||
484 | + y := x | ||
485 | + for i := 0; i < 5; i++ { | ||
486 | + y = y * (2 - x*y) | ||
487 | + } | ||
488 | + return (1 << _W) - (y & _MASK) | ||
489 | +} | ||
490 | + | ||
491 | +// modulusFromNat creates a new modulus from a nat. | ||
492 | +// | ||
493 | +// The nat should be odd, nonzero, and the number of significant bits in the | ||
494 | +// number should be leakable. The nat shouldn't be reused. | ||
495 | +func modulusFromNat(nat *nat) *modulus { | ||
496 | + m := &modulus{} | ||
497 | + m.nat = nat | ||
498 | + size := len(m.nat.limbs) | ||
499 | + for m.nat.limbs[size-1] == 0 { | ||
500 | + size-- | ||
501 | + } | ||
502 | + m.nat.limbs = m.nat.limbs[:size] | ||
503 | + m.leading = _W - bitLen(m.nat.limbs[size-1]) | ||
504 | + m.m0inv = minusInverseModW(m.nat.limbs[0]) | ||
505 | + return m | ||
506 | +} | ||
507 | + | ||
508 | +// bitLen is a version of bits.Len that only leaks the bit length of n, but not | ||
509 | +// its value. bits.Len and bits.LeadingZeros use a lookup table for the | ||
510 | +// low-order bits on some architectures. | ||
511 | +func bitLen(n uint) int { | ||
512 | + var len int | ||
513 | + // We assume, here and elsewhere, that comparison to zero is constant time | ||
514 | + // with respect to different non-zero values. | ||
515 | + for n != 0 { | ||
516 | + len++ | ||
517 | + n >>= 1 | ||
518 | + } | ||
519 | + return len | ||
520 | +} | ||
521 | + | ||
522 | +// bigBitLen is a version of big.Int.BitLen that only leaks the bit length of x, | ||
523 | +// but not its value. big.Int.BitLen uses bits.Len. | ||
524 | +func bigBitLen(x *big.Int) int { | ||
525 | + xLimbs := x.Bits() | ||
526 | + fullLimbs := len(xLimbs) - 1 | ||
527 | + topLimb := uint(xLimbs[len(xLimbs)-1]) | ||
528 | + return fullLimbs*bits.UintSize + bitLen(topLimb) | ||
529 | +} | ||
530 | + | ||
531 | +// modulusSize returns the size of m in bytes. | ||
532 | +func modulusSize(m *modulus) int { | ||
533 | + bits := len(m.nat.limbs)*_W - int(m.leading) | ||
534 | + return (bits + 7) / 8 | ||
535 | +} | ||
536 | + | ||
537 | +// shiftIn calculates x = x << _W + y mod m. | ||
538 | +// | ||
539 | +// This assumes that x is already reduced mod m, and that y < 2^_W. | ||
540 | +func (x *nat) shiftIn(y uint, m *modulus) *nat { | ||
541 | + d := new(nat).resetFor(m) | ||
542 | + | ||
543 | + // Eliminate bounds checks in the loop. | ||
544 | + size := len(m.nat.limbs) | ||
545 | + xLimbs := x.limbs[:size] | ||
546 | + dLimbs := d.limbs[:size] | ||
547 | + mLimbs := m.nat.limbs[:size] | ||
548 | + | ||
549 | + // Each iteration of this loop computes x = 2x + b mod m, where b is a bit | ||
550 | + // from y. Effectively, it left-shifts x and adds y one bit at a time, | ||
551 | + // reducing it every time. | ||
552 | + // | ||
553 | + // To do the reduction, each iteration computes both 2x + b and 2x + b - m. | ||
554 | + // The next iteration (and finally the return line) will use either result | ||
555 | + // based on whether the subtraction underflowed. | ||
556 | + needSubtraction := no | ||
557 | + for i := _W - 1; i >= 0; i-- { | ||
558 | + carry := (y >> i) & 1 | ||
559 | + var borrow uint | ||
560 | + for i := 0; i < size; i++ { | ||
561 | + l := ctSelect(needSubtraction, dLimbs[i], xLimbs[i]) | ||
562 | + | ||
563 | + res := l<<1 + carry | ||
564 | + xLimbs[i] = res & _MASK | ||
565 | + carry = res >> _W | ||
566 | + | ||
567 | + res = xLimbs[i] - mLimbs[i] - borrow | ||
568 | + dLimbs[i] = res & _MASK | ||
569 | + borrow = res >> _W | ||
570 | + } | ||
571 | + // See modAdd for how carry (aka overflow), borrow (aka underflow), and | ||
572 | + // needSubtraction relate. | ||
573 | + needSubtraction = ctEq(carry, borrow) | ||
574 | + } | ||
575 | + return x.assign(needSubtraction, d) | ||
576 | +} | ||
577 | + | ||
578 | +// mod calculates out = x mod m. | ||
579 | +// | ||
580 | +// This works regardless how large the value of x is. | ||
581 | +// | ||
582 | +// The output will be resized to the size of m and overwritten. | ||
583 | +func (out *nat) mod(x *nat, m *modulus) *nat { | ||
584 | + out.resetFor(m) | ||
585 | + // Working our way from the most significant to the least significant limb, | ||
586 | + // we can insert each limb at the least significant position, shifting all | ||
587 | + // previous limbs left by _W. This way each limb will get shifted by the | ||
588 | + // correct number of bits. We can insert at least N - 1 limbs without | ||
589 | + // overflowing m. After that, we need to reduce every time we shift. | ||
590 | + i := len(x.limbs) - 1 | ||
591 | + // For the first N - 1 limbs we can skip the actual shifting and position | ||
592 | + // them at the shifted position, which starts at min(N - 2, i). | ||
593 | + start := len(m.nat.limbs) - 2 | ||
594 | + if i < start { | ||
595 | + start = i | ||
596 | + } | ||
597 | + for j := start; j >= 0; j-- { | ||
598 | + out.limbs[j] = x.limbs[i] | ||
599 | + i-- | ||
600 | + } | ||
601 | + // We shift in the remaining limbs, reducing modulo m each time. | ||
602 | + for i >= 0 { | ||
603 | + out.shiftIn(x.limbs[i], m) | ||
604 | + i-- | ||
605 | + } | ||
606 | + return out | ||
607 | +} | ||
608 | + | ||
609 | +// expandFor ensures out has the right size to work with operations modulo m. | ||
610 | +// | ||
611 | +// This assumes that out has as many or fewer limbs than m, or that the extra | ||
612 | +// limbs are all zero (which may happen when decoding a value that has leading | ||
613 | +// zeroes in its bytes representation that spill over the limb threshold). | ||
614 | +func (out *nat) expandFor(m *modulus) *nat { | ||
615 | + return out.expand(len(m.nat.limbs)) | ||
616 | +} | ||
617 | + | ||
618 | +// resetFor ensures out has the right size to work with operations modulo m. | ||
619 | +// | ||
620 | +// out is zeroed and may start at any size. | ||
621 | +func (out *nat) resetFor(m *modulus) *nat { | ||
622 | + return out.reset(len(m.nat.limbs)) | ||
623 | +} | ||
624 | + | ||
625 | +// modSub computes x = x - y mod m. | ||
626 | +// | ||
627 | +// The length of both operands must be the same as the modulus. Both operands | ||
628 | +// must already be reduced modulo m. | ||
629 | +func (x *nat) modSub(y *nat, m *modulus) *nat { | ||
630 | + underflow := x.sub(yes, y) | ||
631 | + // If the subtraction underflowed, add m. | ||
632 | + x.add(choice(underflow), m.nat) | ||
633 | + return x | ||
634 | +} | ||
635 | + | ||
636 | +// modAdd computes x = x + y mod m. | ||
637 | +// | ||
638 | +// The length of both operands must be the same as the modulus. Both operands | ||
639 | +// must already be reduced modulo m. | ||
640 | +func (x *nat) modAdd(y *nat, m *modulus) *nat { | ||
641 | + overflow := x.add(yes, y) | ||
642 | + underflow := not(x.cmpGeq(m.nat)) // x < m | ||
643 | + | ||
644 | + // Three cases are possible: | ||
645 | + // | ||
646 | + // - overflow = 0, underflow = 0 | ||
647 | + // | ||
648 | + // In this case, addition fits in our limbs, but we can still subtract away | ||
649 | + // m without an underflow, so we need to perform the subtraction to reduce | ||
650 | + // our result. | ||
651 | + // | ||
652 | + // - overflow = 0, underflow = 1 | ||
653 | + // | ||
654 | + // The addition fits in our limbs, but we can't subtract m without | ||
655 | + // underflowing. The result is already reduced. | ||
656 | + // | ||
657 | + // - overflow = 1, underflow = 1 | ||
658 | + // | ||
659 | + // The addition does not fit in our limbs, and the subtraction's borrow | ||
660 | + // would cancel out with the addition's carry. We need to subtract m to | ||
661 | + // reduce our result. | ||
662 | + // | ||
663 | + // The overflow = 1, underflow = 0 case is not possible, because y is at | ||
664 | + // most m - 1, and if adding m - 1 overflows, then subtracting m must | ||
665 | + // necessarily underflow. | ||
666 | + needSubtraction := ctEq(overflow, uint(underflow)) | ||
667 | + | ||
668 | + x.sub(needSubtraction, m.nat) | ||
669 | + return x | ||
670 | +} | ||
671 | + | ||
672 | +// montgomeryRepresentation calculates x = x * R mod m, with R = 2^(_W * n) and | ||
673 | +// n = len(m.nat.limbs). | ||
674 | +// | ||
675 | +// Faster Montgomery multiplication replaces standard modular multiplication for | ||
676 | +// numbers in this representation. | ||
677 | +// | ||
678 | +// This assumes that x is already reduced mod m. | ||
679 | +func (x *nat) montgomeryRepresentation(m *modulus) *nat { | ||
680 | + for i := 0; i < len(m.nat.limbs); i++ { | ||
681 | + x.shiftIn(0, m) // x = x * 2^_W mod m | ||
682 | + } | ||
683 | + return x | ||
684 | +} | ||
685 | + | ||
686 | +// montgomeryMul calculates d = a * b / R mod m, with R = 2^(_W * n) and | ||
687 | +// n = len(m.nat.limbs), using the Montgomery Multiplication technique. | ||
688 | +// | ||
689 | +// All inputs should be the same length, not aliasing d, and already | ||
690 | +// reduced modulo m. d will be resized to the size of m and overwritten. | ||
691 | +func (d *nat) montgomeryMul(a *nat, b *nat, m *modulus) *nat { | ||
692 | + // See https://bearssl.org/bigint.html#montgomery-reduction-and-multiplication | ||
693 | + // for a description of the algorithm. | ||
694 | + | ||
695 | + // Eliminate bounds checks in the loop. | ||
696 | + size := len(m.nat.limbs) | ||
697 | + aLimbs := a.limbs[:size] | ||
698 | + bLimbs := b.limbs[:size] | ||
699 | + dLimbs := d.resetFor(m).limbs[:size] | ||
700 | + mLimbs := m.nat.limbs[:size] | ||
701 | + | ||
702 | + var overflow uint | ||
703 | + for i := 0; i < size; i++ { | ||
704 | + f := ((dLimbs[0] + aLimbs[i]*bLimbs[0]) * m.m0inv) & _MASK | ||
705 | + carry := uint(0) | ||
706 | + for j := 0; j < size; j++ { | ||
707 | + // z = d[j] + a[i] * b[j] + f * m[j] + carry <= 2^(2W+1) - 2^(W+1) + 2^W | ||
708 | + hi, lo := bits.Mul(aLimbs[i], bLimbs[j]) | ||
709 | + z_lo, c := bits.Add(dLimbs[j], lo, 0) | ||
710 | + z_hi, _ := bits.Add(0, hi, c) | ||
711 | + hi, lo = bits.Mul(f, mLimbs[j]) | ||
712 | + z_lo, c = bits.Add(z_lo, lo, 0) | ||
713 | + z_hi, _ = bits.Add(z_hi, hi, c) | ||
714 | + z_lo, c = bits.Add(z_lo, carry, 0) | ||
715 | + z_hi, _ = bits.Add(z_hi, 0, c) | ||
716 | + if j > 0 { | ||
717 | + dLimbs[j-1] = z_lo & _MASK | ||
718 | + } | ||
719 | + carry = z_hi<<1 | z_lo>>_W // carry <= 2^(W+1) - 2 | ||
720 | + } | ||
721 | + z := overflow + carry // z <= 2^(W+1) - 1 | ||
722 | + dLimbs[size-1] = z & _MASK | ||
723 | + overflow = z >> _W // overflow <= 1 | ||
724 | + } | ||
725 | + // See modAdd for how overflow, underflow, and needSubtraction relate. | ||
726 | + underflow := not(d.cmpGeq(m.nat)) // d < m | ||
727 | + needSubtraction := ctEq(overflow, uint(underflow)) | ||
728 | + d.sub(needSubtraction, m.nat) | ||
729 | + | ||
730 | + return d | ||
731 | +} | ||
732 | + | ||
733 | +// modMul calculates x *= y mod m. | ||
734 | +// | ||
735 | +// x and y must already be reduced modulo m, they must share its announced | ||
736 | +// length, and they may not alias. | ||
737 | +func (x *nat) modMul(y *nat, m *modulus) *nat { | ||
738 | + // A Montgomery multiplication by a value out of the Montgomery domain | ||
739 | + // takes the result out of Montgomery representation. | ||
740 | + xR := x.clone().montgomeryRepresentation(m) // xR = x * R mod m | ||
741 | + return x.montgomeryMul(xR, y, m) // x = xR * y / R mod m | ||
742 | +} | ||
743 | + | ||
744 | +// exp calculates out = x^e mod m. | ||
745 | +// | ||
746 | +// The exponent e is represented in big-endian order. The output will be resized | ||
747 | +// to the size of m and overwritten. x must already be reduced modulo m. | ||
748 | +func (out *nat) exp(x *nat, e []byte, m *modulus) *nat { | ||
749 | + // We use a 4 bit window. For our RSA workload, 4 bit windows are faster | ||
750 | + // than 2 bit windows, but use an extra 12 nats worth of scratch space. | ||
751 | + // Using bit sizes that don't divide 8 are more complex to implement. | ||
752 | + table := make([]*nat, (1<<4)-1) // table[i] = x ^ (i+1) | ||
753 | + table[0] = x.clone().montgomeryRepresentation(m) | ||
754 | + for i := 1; i < len(table); i++ { | ||
755 | + table[i] = new(nat).expandFor(m) | ||
756 | + table[i].montgomeryMul(table[i-1], table[0], m) | ||
757 | + } | ||
758 | + | ||
759 | + out.resetFor(m) | ||
760 | + out.limbs[0] = 1 | ||
761 | + out.montgomeryRepresentation(m) | ||
762 | + t0 := new(nat).expandFor(m) | ||
763 | + t1 := new(nat).expandFor(m) | ||
764 | + for _, b := range e { | ||
765 | + for _, j := range []int{4, 0} { | ||
766 | + // Square four times. | ||
767 | + t1.montgomeryMul(out, out, m) | ||
768 | + out.montgomeryMul(t1, t1, m) | ||
769 | + t1.montgomeryMul(out, out, m) | ||
770 | + out.montgomeryMul(t1, t1, m) | ||
771 | + | ||
772 | + // Select x^k in constant time from the table. | ||
773 | + k := uint((b >> j) & 0b1111) | ||
774 | + for i := range table { | ||
775 | + t0.assign(ctEq(k, uint(i+1)), table[i]) | ||
776 | + } | ||
777 | + | ||
778 | + // Multiply by x^k, discarding the result if k = 0. | ||
779 | + t1.montgomeryMul(out, t0, m) | ||
780 | + out.assign(not(ctEq(k, 0)), t1) | ||
781 | + } | ||
782 | + } | ||
783 | + | ||
784 | + // By Montgomery multiplying with 1 not in Montgomery representation, we | ||
785 | + // convert out back from Montgomery representation, because it works out to | ||
786 | + // dividing by R. | ||
787 | + t0.assign(yes, out) | ||
788 | + t1.resetFor(m) | ||
789 | + t1.limbs[0] = 1 | ||
790 | + out.montgomeryMul(t0, t1, m) | ||
791 | + | ||
792 | + return out | ||
793 | +} | ||
794 | diff --git a/src/crypto/rsa/nat_test.go b/src/crypto/rsa/nat_test.go | ||
795 | new file mode 100644 | ||
796 | index 0000000..3e6eb10 | ||
797 | --- /dev/null | ||
798 | +++ b/src/crypto/rsa/nat_test.go | ||
799 | @@ -0,0 +1,384 @@ | ||
800 | +// Copyright 2021 The Go Authors. All rights reserved. | ||
801 | +// Use of this source code is governed by a BSD-style | ||
802 | +// license that can be found in the LICENSE file. | ||
803 | + | ||
804 | +package rsa | ||
805 | + | ||
806 | +import ( | ||
807 | + "bytes" | ||
808 | + "math/big" | ||
809 | + "math/bits" | ||
810 | + "math/rand" | ||
811 | + "reflect" | ||
812 | + "testing" | ||
813 | + "testing/quick" | ||
814 | +) | ||
815 | + | ||
816 | +// Generate generates an even nat. It's used by testing/quick to produce random | ||
817 | +// *nat values for quick.Check invocations. | ||
818 | +func (*nat) Generate(r *rand.Rand, size int) reflect.Value { | ||
819 | + limbs := make([]uint, size) | ||
820 | + for i := 0; i < size; i++ { | ||
821 | + limbs[i] = uint(r.Uint64()) & ((1 << _W) - 2) | ||
822 | + } | ||
823 | + return reflect.ValueOf(&nat{limbs}) | ||
824 | +} | ||
825 | + | ||
826 | +func testModAddCommutative(a *nat, b *nat) bool { | ||
827 | + mLimbs := make([]uint, len(a.limbs)) | ||
828 | + for i := 0; i < len(mLimbs); i++ { | ||
829 | + mLimbs[i] = _MASK | ||
830 | + } | ||
831 | + m := modulusFromNat(&nat{mLimbs}) | ||
832 | + aPlusB := a.clone() | ||
833 | + aPlusB.modAdd(b, m) | ||
834 | + bPlusA := b.clone() | ||
835 | + bPlusA.modAdd(a, m) | ||
836 | + return aPlusB.cmpEq(bPlusA) == 1 | ||
837 | +} | ||
838 | + | ||
839 | +func TestModAddCommutative(t *testing.T) { | ||
840 | + err := quick.Check(testModAddCommutative, &quick.Config{}) | ||
841 | + if err != nil { | ||
842 | + t.Error(err) | ||
843 | + } | ||
844 | +} | ||
845 | + | ||
846 | +func testModSubThenAddIdentity(a *nat, b *nat) bool { | ||
847 | + mLimbs := make([]uint, len(a.limbs)) | ||
848 | + for i := 0; i < len(mLimbs); i++ { | ||
849 | + mLimbs[i] = _MASK | ||
850 | + } | ||
851 | + m := modulusFromNat(&nat{mLimbs}) | ||
852 | + original := a.clone() | ||
853 | + a.modSub(b, m) | ||
854 | + a.modAdd(b, m) | ||
855 | + return a.cmpEq(original) == 1 | ||
856 | +} | ||
857 | + | ||
858 | +func TestModSubThenAddIdentity(t *testing.T) { | ||
859 | + err := quick.Check(testModSubThenAddIdentity, &quick.Config{}) | ||
860 | + if err != nil { | ||
861 | + t.Error(err) | ||
862 | + } | ||
863 | +} | ||
864 | + | ||
865 | +func testMontgomeryRoundtrip(a *nat) bool { | ||
866 | + one := &nat{make([]uint, len(a.limbs))} | ||
867 | + one.limbs[0] = 1 | ||
868 | + aPlusOne := a.clone() | ||
869 | + aPlusOne.add(1, one) | ||
870 | + m := modulusFromNat(aPlusOne) | ||
871 | + monty := a.clone() | ||
872 | + monty.montgomeryRepresentation(m) | ||
873 | + aAgain := monty.clone() | ||
874 | + aAgain.montgomeryMul(monty, one, m) | ||
875 | + return a.cmpEq(aAgain) == 1 | ||
876 | +} | ||
877 | + | ||
878 | +func TestMontgomeryRoundtrip(t *testing.T) { | ||
879 | + err := quick.Check(testMontgomeryRoundtrip, &quick.Config{}) | ||
880 | + if err != nil { | ||
881 | + t.Error(err) | ||
882 | + } | ||
883 | +} | ||
884 | + | ||
885 | +func TestFromBig(t *testing.T) { | ||
886 | + expected := []byte{0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} | ||
887 | + theBig := new(big.Int).SetBytes(expected) | ||
888 | + actual := natFromBig(theBig).fillBytes(make([]byte, len(expected))) | ||
889 | + if !bytes.Equal(actual, expected) { | ||
890 | + t.Errorf("%+x != %+x", actual, expected) | ||
891 | + } | ||
892 | +} | ||
893 | + | ||
894 | +func TestFillBytes(t *testing.T) { | ||
895 | + xBytes := []byte{0xAA, 0xFF, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88} | ||
896 | + x := natFromBytes(xBytes) | ||
897 | + for l := 20; l >= len(xBytes); l-- { | ||
898 | + buf := make([]byte, l) | ||
899 | + rand.Read(buf) | ||
900 | + actual := x.fillBytes(buf) | ||
901 | + expected := make([]byte, l) | ||
902 | + copy(expected[l-len(xBytes):], xBytes) | ||
903 | + if !bytes.Equal(actual, expected) { | ||
904 | + t.Errorf("%d: %+v != %+v", l, actual, expected) | ||
905 | + } | ||
906 | + } | ||
907 | + for l := len(xBytes) - 1; l >= 0; l-- { | ||
908 | + (func() { | ||
909 | + defer func() { | ||
910 | + if recover() == nil { | ||
911 | + t.Errorf("%d: expected panic", l) | ||
912 | + } | ||
913 | + }() | ||
914 | + x.fillBytes(make([]byte, l)) | ||
915 | + })() | ||
916 | + } | ||
917 | +} | ||
918 | + | ||
919 | +func TestFromBytes(t *testing.T) { | ||
920 | + f := func(xBytes []byte) bool { | ||
921 | + if len(xBytes) == 0 { | ||
922 | + return true | ||
923 | + } | ||
924 | + actual := natFromBytes(xBytes).fillBytes(make([]byte, len(xBytes))) | ||
925 | + if !bytes.Equal(actual, xBytes) { | ||
926 | + t.Errorf("%+x != %+x", actual, xBytes) | ||
927 | + return false | ||
928 | + } | ||
929 | + return true | ||
930 | + } | ||
931 | + | ||
932 | + err := quick.Check(f, &quick.Config{}) | ||
933 | + if err != nil { | ||
934 | + t.Error(err) | ||
935 | + } | ||
936 | + | ||
937 | + f([]byte{0xFF, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}) | ||
938 | + f(bytes.Repeat([]byte{0xFF}, _W)) | ||
939 | +} | ||
940 | + | ||
941 | +func TestShiftIn(t *testing.T) { | ||
942 | + if bits.UintSize != 64 { | ||
943 | + t.Skip("examples are only valid in 64 bit") | ||
944 | + } | ||
945 | + examples := []struct { | ||
946 | + m, x, expected []byte | ||
947 | + y uint64 | ||
948 | + }{{ | ||
949 | + m: []byte{13}, | ||
950 | + x: []byte{0}, | ||
951 | + y: 0x7FFF_FFFF_FFFF_FFFF, | ||
952 | + expected: []byte{7}, | ||
953 | + }, { | ||
954 | + m: []byte{13}, | ||
955 | + x: []byte{7}, | ||
956 | + y: 0x7FFF_FFFF_FFFF_FFFF, | ||
957 | + expected: []byte{11}, | ||
958 | + }, { | ||
959 | + m: []byte{0x06, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d}, | ||
960 | + x: make([]byte, 9), | ||
961 | + y: 0x7FFF_FFFF_FFFF_FFFF, | ||
962 | + expected: []byte{0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, | ||
963 | + }, { | ||
964 | + m: []byte{0x06, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d}, | ||
965 | + x: []byte{0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, | ||
966 | + y: 0, | ||
967 | + expected: []byte{0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08}, | ||
968 | + }} | ||
969 | + | ||
970 | + for i, tt := range examples { | ||
971 | + m := modulusFromNat(natFromBytes(tt.m)) | ||
972 | + got := natFromBytes(tt.x).expandFor(m).shiftIn(uint(tt.y), m) | ||
973 | + if got.cmpEq(natFromBytes(tt.expected).expandFor(m)) != 1 { | ||
974 | + t.Errorf("%d: got %x, expected %x", i, got, tt.expected) | ||
975 | + } | ||
976 | + } | ||
977 | +} | ||
978 | + | ||
979 | +func TestModulusAndNatSizes(t *testing.T) { | ||
980 | + // These are 126 bit (2 * _W on 64-bit architectures) values, serialized as | ||
981 | + // 128 bits worth of bytes. If leading zeroes are stripped, they fit in two | ||
982 | + // limbs, if they are not, they fit in three. This can be a problem because | ||
983 | + // modulus strips leading zeroes and nat does not. | ||
984 | + m := modulusFromNat(natFromBytes([]byte{ | ||
985 | + 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
986 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff})) | ||
987 | + x := natFromBytes([]byte{ | ||
988 | + 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
989 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe}) | ||
990 | + x.expandFor(m) // must not panic for shrinking | ||
991 | +} | ||
992 | + | ||
993 | +func TestExpand(t *testing.T) { | ||
994 | + sliced := []uint{1, 2, 3, 4} | ||
995 | + examples := []struct { | ||
996 | + in []uint | ||
997 | + n int | ||
998 | + out []uint | ||
999 | + }{{ | ||
1000 | + []uint{1, 2}, | ||
1001 | + 4, | ||
1002 | + []uint{1, 2, 0, 0}, | ||
1003 | + }, { | ||
1004 | + sliced[:2], | ||
1005 | + 4, | ||
1006 | + []uint{1, 2, 0, 0}, | ||
1007 | + }, { | ||
1008 | + []uint{1, 2}, | ||
1009 | + 2, | ||
1010 | + []uint{1, 2}, | ||
1011 | + }, { | ||
1012 | + []uint{1, 2, 0}, | ||
1013 | + 2, | ||
1014 | + []uint{1, 2}, | ||
1015 | + }} | ||
1016 | + | ||
1017 | + for i, tt := range examples { | ||
1018 | + got := (&nat{tt.in}).expand(tt.n) | ||
1019 | + if len(got.limbs) != len(tt.out) || got.cmpEq(&nat{tt.out}) != 1 { | ||
1020 | + t.Errorf("%d: got %x, expected %x", i, got, tt.out) | ||
1021 | + } | ||
1022 | + } | ||
1023 | +} | ||
1024 | + | ||
1025 | +func TestMod(t *testing.T) { | ||
1026 | + m := modulusFromNat(natFromBytes([]byte{0x06, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d})) | ||
1027 | + x := natFromBytes([]byte{0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}) | ||
1028 | + out := new(nat) | ||
1029 | + out.mod(x, m) | ||
1030 | + expected := natFromBytes([]byte{0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09}) | ||
1031 | + if out.cmpEq(expected) != 1 { | ||
1032 | + t.Errorf("%+v != %+v", out, expected) | ||
1033 | + } | ||
1034 | +} | ||
1035 | + | ||
1036 | +func TestModSub(t *testing.T) { | ||
1037 | + m := modulusFromNat(&nat{[]uint{13}}) | ||
1038 | + x := &nat{[]uint{6}} | ||
1039 | + y := &nat{[]uint{7}} | ||
1040 | + x.modSub(y, m) | ||
1041 | + expected := &nat{[]uint{12}} | ||
1042 | + if x.cmpEq(expected) != 1 { | ||
1043 | + t.Errorf("%+v != %+v", x, expected) | ||
1044 | + } | ||
1045 | + x.modSub(y, m) | ||
1046 | + expected = &nat{[]uint{5}} | ||
1047 | + if x.cmpEq(expected) != 1 { | ||
1048 | + t.Errorf("%+v != %+v", x, expected) | ||
1049 | + } | ||
1050 | +} | ||
1051 | + | ||
1052 | +func TestModAdd(t *testing.T) { | ||
1053 | + m := modulusFromNat(&nat{[]uint{13}}) | ||
1054 | + x := &nat{[]uint{6}} | ||
1055 | + y := &nat{[]uint{7}} | ||
1056 | + x.modAdd(y, m) | ||
1057 | + expected := &nat{[]uint{0}} | ||
1058 | + if x.cmpEq(expected) != 1 { | ||
1059 | + t.Errorf("%+v != %+v", x, expected) | ||
1060 | + } | ||
1061 | + x.modAdd(y, m) | ||
1062 | + expected = &nat{[]uint{7}} | ||
1063 | + if x.cmpEq(expected) != 1 { | ||
1064 | + t.Errorf("%+v != %+v", x, expected) | ||
1065 | + } | ||
1066 | +} | ||
1067 | + | ||
1068 | +func TestExp(t *testing.T) { | ||
1069 | + m := modulusFromNat(&nat{[]uint{13}}) | ||
1070 | + x := &nat{[]uint{3}} | ||
1071 | + out := &nat{[]uint{0}} | ||
1072 | + out.exp(x, []byte{12}, m) | ||
1073 | + expected := &nat{[]uint{1}} | ||
1074 | + if out.cmpEq(expected) != 1 { | ||
1075 | + t.Errorf("%+v != %+v", out, expected) | ||
1076 | + } | ||
1077 | +} | ||
1078 | + | ||
1079 | +func makeBenchmarkModulus() *modulus { | ||
1080 | + m := make([]uint, 32) | ||
1081 | + for i := 0; i < 32; i++ { | ||
1082 | + m[i] = _MASK | ||
1083 | + } | ||
1084 | + return modulusFromNat(&nat{limbs: m}) | ||
1085 | +} | ||
1086 | + | ||
1087 | +func makeBenchmarkValue() *nat { | ||
1088 | + x := make([]uint, 32) | ||
1089 | + for i := 0; i < 32; i++ { | ||
1090 | + x[i] = _MASK - 1 | ||
1091 | + } | ||
1092 | + return &nat{limbs: x} | ||
1093 | +} | ||
1094 | + | ||
1095 | +func makeBenchmarkExponent() []byte { | ||
1096 | + e := make([]byte, 256) | ||
1097 | + for i := 0; i < 32; i++ { | ||
1098 | + e[i] = 0xFF | ||
1099 | + } | ||
1100 | + return e | ||
1101 | +} | ||
1102 | + | ||
1103 | +func BenchmarkModAdd(b *testing.B) { | ||
1104 | + x := makeBenchmarkValue() | ||
1105 | + y := makeBenchmarkValue() | ||
1106 | + m := makeBenchmarkModulus() | ||
1107 | + | ||
1108 | + b.ResetTimer() | ||
1109 | + for i := 0; i < b.N; i++ { | ||
1110 | + x.modAdd(y, m) | ||
1111 | + } | ||
1112 | +} | ||
1113 | + | ||
1114 | +func BenchmarkModSub(b *testing.B) { | ||
1115 | + x := makeBenchmarkValue() | ||
1116 | + y := makeBenchmarkValue() | ||
1117 | + m := makeBenchmarkModulus() | ||
1118 | + | ||
1119 | + b.ResetTimer() | ||
1120 | + for i := 0; i < b.N; i++ { | ||
1121 | + x.modSub(y, m) | ||
1122 | + } | ||
1123 | +} | ||
1124 | + | ||
1125 | +func BenchmarkMontgomeryRepr(b *testing.B) { | ||
1126 | + x := makeBenchmarkValue() | ||
1127 | + m := makeBenchmarkModulus() | ||
1128 | + | ||
1129 | + b.ResetTimer() | ||
1130 | + for i := 0; i < b.N; i++ { | ||
1131 | + x.montgomeryRepresentation(m) | ||
1132 | + } | ||
1133 | +} | ||
1134 | + | ||
1135 | +func BenchmarkMontgomeryMul(b *testing.B) { | ||
1136 | + x := makeBenchmarkValue() | ||
1137 | + y := makeBenchmarkValue() | ||
1138 | + out := makeBenchmarkValue() | ||
1139 | + m := makeBenchmarkModulus() | ||
1140 | + | ||
1141 | + b.ResetTimer() | ||
1142 | + for i := 0; i < b.N; i++ { | ||
1143 | + out.montgomeryMul(x, y, m) | ||
1144 | + } | ||
1145 | +} | ||
1146 | + | ||
1147 | +func BenchmarkModMul(b *testing.B) { | ||
1148 | + x := makeBenchmarkValue() | ||
1149 | + y := makeBenchmarkValue() | ||
1150 | + m := makeBenchmarkModulus() | ||
1151 | + | ||
1152 | + b.ResetTimer() | ||
1153 | + for i := 0; i < b.N; i++ { | ||
1154 | + x.modMul(y, m) | ||
1155 | + } | ||
1156 | +} | ||
1157 | + | ||
1158 | +func BenchmarkExpBig(b *testing.B) { | ||
1159 | + out := new(big.Int) | ||
1160 | + exponentBytes := makeBenchmarkExponent() | ||
1161 | + x := new(big.Int).SetBytes(exponentBytes) | ||
1162 | + e := new(big.Int).SetBytes(exponentBytes) | ||
1163 | + n := new(big.Int).SetBytes(exponentBytes) | ||
1164 | + one := new(big.Int).SetUint64(1) | ||
1165 | + n.Add(n, one) | ||
1166 | + | ||
1167 | + b.ResetTimer() | ||
1168 | + for i := 0; i < b.N; i++ { | ||
1169 | + out.Exp(x, e, n) | ||
1170 | + } | ||
1171 | +} | ||
1172 | + | ||
1173 | +func BenchmarkExp(b *testing.B) { | ||
1174 | + x := makeBenchmarkValue() | ||
1175 | + e := makeBenchmarkExponent() | ||
1176 | + out := makeBenchmarkValue() | ||
1177 | + m := makeBenchmarkModulus() | ||
1178 | + | ||
1179 | + b.ResetTimer() | ||
1180 | + for i := 0; i < b.N; i++ { | ||
1181 | + out.exp(x, e, m) | ||
1182 | + } | ||
1183 | +} | ||
1184 | diff --git a/src/crypto/rsa/pkcs1v15.go b/src/crypto/rsa/pkcs1v15.go | ||
1185 | index a216be3..ce89f92 100644 | ||
1186 | --- a/src/crypto/rsa/pkcs1v15.go | ||
1187 | +++ b/src/crypto/rsa/pkcs1v15.go | ||
1188 | @@ -9,7 +9,6 @@ import ( | ||
1189 | "crypto/subtle" | ||
1190 | "errors" | ||
1191 | "io" | ||
1192 | - "math/big" | ||
1193 | |||
1194 | "crypto/internal/randutil" | ||
1195 | ) | ||
1196 | @@ -58,14 +57,11 @@ func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) ([]byte, error) | ||
1197 | em[len(em)-len(msg)-1] = 0 | ||
1198 | copy(mm, msg) | ||
1199 | |||
1200 | - m := new(big.Int).SetBytes(em) | ||
1201 | - c := encrypt(new(big.Int), pub, m) | ||
1202 | - | ||
1203 | - return c.FillBytes(em), nil | ||
1204 | + return encrypt(pub, em), nil | ||
1205 | } | ||
1206 | |||
1207 | // DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5. | ||
1208 | -// If rand != nil, it uses RSA blinding to avoid timing side-channel attacks. | ||
1209 | +// The rand parameter is legacy and ignored, and it can be as nil. | ||
1210 | // | ||
1211 | // Note that whether this function returns an error or not discloses secret | ||
1212 | // information. If an attacker can cause this function to run repeatedly and | ||
1213 | @@ -76,7 +72,7 @@ func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) ([]byt | ||
1214 | if err := checkPub(&priv.PublicKey); err != nil { | ||
1215 | return nil, err | ||
1216 | } | ||
1217 | - valid, out, index, err := decryptPKCS1v15(rand, priv, ciphertext) | ||
1218 | + valid, out, index, err := decryptPKCS1v15(priv, ciphertext) | ||
1219 | if err != nil { | ||
1220 | return nil, err | ||
1221 | } | ||
1222 | @@ -87,7 +83,7 @@ func DecryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) ([]byt | ||
1223 | } | ||
1224 | |||
1225 | // DecryptPKCS1v15SessionKey decrypts a session key using RSA and the padding scheme from PKCS#1 v1.5. | ||
1226 | -// If rand != nil, it uses RSA blinding to avoid timing side-channel attacks. | ||
1227 | +// The rand parameter is legacy and ignored, and it can be as nil. | ||
1228 | // It returns an error if the ciphertext is the wrong length or if the | ||
1229 | // ciphertext is greater than the public modulus. Otherwise, no error is | ||
1230 | // returned. If the padding is valid, the resulting plaintext message is copied | ||
1231 | @@ -114,7 +110,7 @@ func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []by | ||
1232 | return ErrDecryption | ||
1233 | } | ||
1234 | |||
1235 | - valid, em, index, err := decryptPKCS1v15(rand, priv, ciphertext) | ||
1236 | + valid, em, index, err := decryptPKCS1v15(priv, ciphertext) | ||
1237 | if err != nil { | ||
1238 | return err | ||
1239 | } | ||
1240 | @@ -130,26 +126,24 @@ func DecryptPKCS1v15SessionKey(rand io.Reader, priv *PrivateKey, ciphertext []by | ||
1241 | return nil | ||
1242 | } | ||
1243 | |||
1244 | -// decryptPKCS1v15 decrypts ciphertext using priv and blinds the operation if | ||
1245 | -// rand is not nil. It returns one or zero in valid that indicates whether the | ||
1246 | -// plaintext was correctly structured. In either case, the plaintext is | ||
1247 | -// returned in em so that it may be read independently of whether it was valid | ||
1248 | -// in order to maintain constant memory access patterns. If the plaintext was | ||
1249 | -// valid then index contains the index of the original message in em. | ||
1250 | -func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid int, em []byte, index int, err error) { | ||
1251 | +// decryptPKCS1v15 decrypts ciphertext using priv. It returns one or zero in | ||
1252 | +// valid that indicates whether the plaintext was correctly structured. | ||
1253 | +// In either case, the plaintext is returned in em so that it may be read | ||
1254 | +// independently of whether it was valid in order to maintain constant memory | ||
1255 | +// access patterns. If the plaintext was valid then index contains the index of | ||
1256 | +// the original message in em, to allow constant time padding removal. | ||
1257 | +func decryptPKCS1v15(priv *PrivateKey, ciphertext []byte) (valid int, em []byte, index int, err error) { | ||
1258 | k := priv.Size() | ||
1259 | if k < 11 { | ||
1260 | err = ErrDecryption | ||
1261 | return | ||
1262 | } | ||
1263 | |||
1264 | - c := new(big.Int).SetBytes(ciphertext) | ||
1265 | - m, err := decrypt(rand, priv, c) | ||
1266 | + em, err = decrypt(priv, ciphertext) | ||
1267 | if err != nil { | ||
1268 | return | ||
1269 | } | ||
1270 | |||
1271 | - em = m.FillBytes(make([]byte, k)) | ||
1272 | firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0) | ||
1273 | secondByteIsTwo := subtle.ConstantTimeByteEq(em[1], 2) | ||
1274 | |||
1275 | @@ -221,8 +215,7 @@ var hashPrefixes = map[crypto.Hash][]byte{ | ||
1276 | // function. If hash is zero, hashed is signed directly. This isn't | ||
1277 | // advisable except for interoperability. | ||
1278 | // | ||
1279 | -// If rand is not nil then RSA blinding will be used to avoid timing | ||
1280 | -// side-channel attacks. | ||
1281 | +// The rand parameter is legacy and ignored, and it can be as nil. | ||
1282 | // | ||
1283 | // This function is deterministic. Thus, if the set of possible | ||
1284 | // messages is small, an attacker may be able to build a map from | ||
1285 | @@ -249,13 +242,7 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []b | ||
1286 | copy(em[k-tLen:k-hashLen], prefix) | ||
1287 | copy(em[k-hashLen:k], hashed) | ||
1288 | |||
1289 | - m := new(big.Int).SetBytes(em) | ||
1290 | - c, err := decryptAndCheck(rand, priv, m) | ||
1291 | - if err != nil { | ||
1292 | - return nil, err | ||
1293 | - } | ||
1294 | - | ||
1295 | - return c.FillBytes(em), nil | ||
1296 | + return decryptAndCheck(priv, em) | ||
1297 | } | ||
1298 | |||
1299 | // VerifyPKCS1v15 verifies an RSA PKCS#1 v1.5 signature. | ||
1300 | @@ -275,9 +262,7 @@ func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte) | ||
1301 | return ErrVerification | ||
1302 | } | ||
1303 | |||
1304 | - c := new(big.Int).SetBytes(sig) | ||
1305 | - m := encrypt(new(big.Int), pub, c) | ||
1306 | - em := m.FillBytes(make([]byte, k)) | ||
1307 | + em := encrypt(pub, sig) | ||
1308 | // EM = 0x00 || 0x01 || PS || 0x00 || T | ||
1309 | |||
1310 | ok := subtle.ConstantTimeByteEq(em[0], 0) | ||
1311 | diff --git a/src/crypto/rsa/pss.go b/src/crypto/rsa/pss.go | ||
1312 | index 814522d..eaba4be 100644 | ||
1313 | --- a/src/crypto/rsa/pss.go | ||
1314 | +++ b/src/crypto/rsa/pss.go | ||
1315 | @@ -12,7 +12,6 @@ import ( | ||
1316 | "errors" | ||
1317 | "hash" | ||
1318 | "io" | ||
1319 | - "math/big" | ||
1320 | ) | ||
1321 | |||
1322 | // Per RFC 8017, Section 9.1 | ||
1323 | @@ -207,19 +206,27 @@ func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error { | ||
1324 | // Note that hashed must be the result of hashing the input message using the | ||
1325 | // given hash function. salt is a random sequence of bytes whose length will be | ||
1326 | // later used to verify the signature. | ||
1327 | -func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) ([]byte, error) { | ||
1328 | - emBits := priv.N.BitLen() - 1 | ||
1329 | +func signPSSWithSalt(priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) ([]byte, error) { | ||
1330 | + emBits := bigBitLen(priv.N) - 1 | ||
1331 | em, err := emsaPSSEncode(hashed, emBits, salt, hash.New()) | ||
1332 | if err != nil { | ||
1333 | return nil, err | ||
1334 | } | ||
1335 | - m := new(big.Int).SetBytes(em) | ||
1336 | - c, err := decryptAndCheck(rand, priv, m) | ||
1337 | - if err != nil { | ||
1338 | - return nil, err | ||
1339 | + | ||
1340 | + // RFC 8017: "Note that the octet length of EM will be one less than k if | ||
1341 | + // modBits - 1 is divisible by 8 and equal to k otherwise, where k is the | ||
1342 | + // length in octets of the RSA modulus n." | ||
1343 | + // | ||
1344 | + // This is extremely annoying, as all other encrypt and decrypt inputs are | ||
1345 | + // always the exact same size as the modulus. Since it only happens for | ||
1346 | + // weird modulus sizes, fix it by padding inefficiently. | ||
1347 | + if emLen, k := len(em), priv.Size(); emLen < k { | ||
1348 | + emNew := make([]byte, k) | ||
1349 | + copy(emNew[k-emLen:], em) | ||
1350 | + em = emNew | ||
1351 | } | ||
1352 | - s := make([]byte, priv.Size()) | ||
1353 | - return c.FillBytes(s), nil | ||
1354 | + | ||
1355 | + return decryptAndCheck(priv, em) | ||
1356 | } | ||
1357 | |||
1358 | const ( | ||
1359 | @@ -269,7 +276,7 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, | ||
1360 | saltLength := opts.saltLength() | ||
1361 | switch saltLength { | ||
1362 | case PSSSaltLengthAuto: | ||
1363 | - saltLength = (priv.N.BitLen()-1+7)/8 - 2 - hash.Size() | ||
1364 | + saltLength = (bigBitLen(priv.N)-1+7)/8 - 2 - hash.Size() | ||
1365 | case PSSSaltLengthEqualsHash: | ||
1366 | saltLength = hash.Size() | ||
1367 | } | ||
1368 | @@ -278,7 +285,7 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, | ||
1369 | if _, err := io.ReadFull(rand, salt); err != nil { | ||
1370 | return nil, err | ||
1371 | } | ||
1372 | - return signPSSWithSalt(rand, priv, hash, digest, salt) | ||
1373 | + return signPSSWithSalt(priv, hash, digest, salt) | ||
1374 | } | ||
1375 | |||
1376 | // VerifyPSS verifies a PSS signature. | ||
1377 | @@ -291,13 +298,22 @@ func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts | ||
1378 | if len(sig) != pub.Size() { | ||
1379 | return ErrVerification | ||
1380 | } | ||
1381 | - s := new(big.Int).SetBytes(sig) | ||
1382 | - m := encrypt(new(big.Int), pub, s) | ||
1383 | - emBits := pub.N.BitLen() - 1 | ||
1384 | + | ||
1385 | + emBits := bigBitLen(pub.N) - 1 | ||
1386 | emLen := (emBits + 7) / 8 | ||
1387 | - if m.BitLen() > emLen*8 { | ||
1388 | - return ErrVerification | ||
1389 | + em := encrypt(pub, sig) | ||
1390 | + | ||
1391 | + // Like in signPSSWithSalt, deal with mismatches between emLen and the size | ||
1392 | + // of the modulus. The spec would have us wire emLen into the encoding | ||
1393 | + // function, but we'd rather always encode to the size of the modulus and | ||
1394 | + // then strip leading zeroes if necessary. This only happens for weird | ||
1395 | + // modulus sizes anyway. | ||
1396 | + for len(em) > emLen && len(em) > 0 { | ||
1397 | + if em[0] != 0 { | ||
1398 | + return ErrVerification | ||
1399 | + } | ||
1400 | + em = em[1:] | ||
1401 | } | ||
1402 | - em := m.FillBytes(make([]byte, emLen)) | ||
1403 | + | ||
1404 | return emsaPSSVerify(digest, em, emBits, opts.saltLength(), hash.New()) | ||
1405 | } | ||
1406 | diff --git a/src/crypto/rsa/pss_test.go b/src/crypto/rsa/pss_test.go | ||
1407 | index c3a6d46..d018b43 100644 | ||
1408 | --- a/src/crypto/rsa/pss_test.go | ||
1409 | +++ b/src/crypto/rsa/pss_test.go | ||
1410 | @@ -233,7 +233,10 @@ func TestPSSSigning(t *testing.T) { | ||
1411 | } | ||
1412 | } | ||
1413 | |||
1414 | -func TestSignWithPSSSaltLengthAuto(t *testing.T) { | ||
1415 | +func TestPSS513(t *testing.T) { | ||
1416 | + // See Issue 42741, and separately, RFC 8017: "Note that the octet length of | ||
1417 | + // EM will be one less than k if modBits - 1 is divisible by 8 and equal to | ||
1418 | + // k otherwise, where k is the length in octets of the RSA modulus n." | ||
1419 | key, err := GenerateKey(rand.Reader, 513) | ||
1420 | if err != nil { | ||
1421 | t.Fatal(err) | ||
1422 | @@ -246,8 +249,9 @@ func TestSignWithPSSSaltLengthAuto(t *testing.T) { | ||
1423 | if err != nil { | ||
1424 | t.Fatal(err) | ||
1425 | } | ||
1426 | - if len(signature) == 0 { | ||
1427 | - t.Fatal("empty signature returned") | ||
1428 | + err = VerifyPSS(&key.PublicKey, crypto.SHA256, digest[:], signature, nil) | ||
1429 | + if err != nil { | ||
1430 | + t.Error(err) | ||
1431 | } | ||
1432 | } | ||
1433 | |||
1434 | diff --git a/src/crypto/rsa/rsa.go b/src/crypto/rsa/rsa.go | ||
1435 | index 5a00ed2..29d9d31 100644 | ||
1436 | --- a/src/crypto/rsa/rsa.go | ||
1437 | +++ b/src/crypto/rsa/rsa.go | ||
1438 | @@ -19,13 +19,17 @@ | ||
1439 | // over the public key primitive, the PrivateKey type implements the | ||
1440 | // Decrypter and Signer interfaces from the crypto package. | ||
1441 | // | ||
1442 | -// The RSA operations in this package are not implemented using constant-time algorithms. | ||
1443 | +// Operations in this package are implemented using constant-time algorithms, | ||
1444 | +// except for [GenerateKey], [PrivateKey.Precompute], and [PrivateKey.Validate]. | ||
1445 | +// Every other operation only leaks the bit size of the involved values, which | ||
1446 | +// all depend on the selected key size. | ||
1447 | package rsa | ||
1448 | |||
1449 | import ( | ||
1450 | "crypto" | ||
1451 | "crypto/rand" | ||
1452 | "crypto/subtle" | ||
1453 | + "encoding/binary" | ||
1454 | "errors" | ||
1455 | "hash" | ||
1456 | "io" | ||
1457 | @@ -35,7 +39,6 @@ import ( | ||
1458 | "crypto/internal/randutil" | ||
1459 | ) | ||
1460 | |||
1461 | -var bigZero = big.NewInt(0) | ||
1462 | var bigOne = big.NewInt(1) | ||
1463 | |||
1464 | // A PublicKey represents the public part of an RSA key. | ||
1465 | @@ -47,7 +50,7 @@ type PublicKey struct { | ||
1466 | // Size returns the modulus size in bytes. Raw signatures and ciphertexts | ||
1467 | // for or by this public key will have the same size. | ||
1468 | func (pub *PublicKey) Size() int { | ||
1469 | - return (pub.N.BitLen() + 7) / 8 | ||
1470 | + return (bigBitLen(pub.N) + 7) / 8 | ||
1471 | } | ||
1472 | |||
1473 | // OAEPOptions is an interface for passing options to OAEP decryption using the | ||
1474 | @@ -351,10 +354,19 @@ func mgf1XOR(out []byte, hash hash.Hash, seed []byte) { | ||
1475 | // too large for the size of the public key. | ||
1476 | var ErrMessageTooLong = errors.New("crypto/rsa: message too long for RSA public key size") | ||
1477 | |||
1478 | -func encrypt(c *big.Int, pub *PublicKey, m *big.Int) *big.Int { | ||
1479 | - e := big.NewInt(int64(pub.E)) | ||
1480 | - c.Exp(m, e, pub.N) | ||
1481 | - return c | ||
1482 | +func encrypt(pub *PublicKey, plaintext []byte) []byte { | ||
1483 | + | ||
1484 | + N := modulusFromNat(natFromBig(pub.N)) | ||
1485 | + m := natFromBytes(plaintext).expandFor(N) | ||
1486 | + | ||
1487 | + e := make([]byte, 8) | ||
1488 | + binary.BigEndian.PutUint64(e, uint64(pub.E)) | ||
1489 | + for len(e) > 1 && e[0] == 0 { | ||
1490 | + e = e[1:] | ||
1491 | + } | ||
1492 | + | ||
1493 | + out := make([]byte, modulusSize(N)) | ||
1494 | + return new(nat).exp(m, e, N).fillBytes(out) | ||
1495 | } | ||
1496 | |||
1497 | // EncryptOAEP encrypts the given message with RSA-OAEP. | ||
1498 | @@ -404,12 +416,7 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l | ||
1499 | mgf1XOR(db, hash, seed) | ||
1500 | mgf1XOR(seed, hash, db) | ||
1501 | |||
1502 | - m := new(big.Int) | ||
1503 | - m.SetBytes(em) | ||
1504 | - c := encrypt(new(big.Int), pub, m) | ||
1505 | - | ||
1506 | - out := make([]byte, k) | ||
1507 | - return c.FillBytes(out), nil | ||
1508 | + return encrypt(pub, em), nil | ||
1509 | } | ||
1510 | |||
1511 | // ErrDecryption represents a failure to decrypt a message. | ||
1512 | @@ -451,98 +458,71 @@ func (priv *PrivateKey) Precompute() { | ||
1513 | } | ||
1514 | } | ||
1515 | |||
1516 | -// decrypt performs an RSA decryption, resulting in a plaintext integer. If a | ||
1517 | -// random source is given, RSA blinding is used. | ||
1518 | -func decrypt(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err error) { | ||
1519 | - // TODO(agl): can we get away with reusing blinds? | ||
1520 | - if c.Cmp(priv.N) > 0 { | ||
1521 | - err = ErrDecryption | ||
1522 | - return | ||
1523 | +// decrypt performs an RSA decryption of ciphertext into out. | ||
1524 | +func decrypt(priv *PrivateKey, ciphertext []byte) ([]byte, error) { | ||
1525 | + | ||
1526 | + N := modulusFromNat(natFromBig(priv.N)) | ||
1527 | + c := natFromBytes(ciphertext).expandFor(N) | ||
1528 | + if c.cmpGeq(N.nat) == 1 { | ||
1529 | + return nil, ErrDecryption | ||
1530 | } | ||
1531 | if priv.N.Sign() == 0 { | ||
1532 | return nil, ErrDecryption | ||
1533 | } | ||
1534 | |||
1535 | - var ir *big.Int | ||
1536 | - if random != nil { | ||
1537 | - randutil.MaybeReadByte(random) | ||
1538 | - | ||
1539 | - // Blinding enabled. Blinding involves multiplying c by r^e. | ||
1540 | - // Then the decryption operation performs (m^e * r^e)^d mod n | ||
1541 | - // which equals mr mod n. The factor of r can then be removed | ||
1542 | - // by multiplying by the multiplicative inverse of r. | ||
1543 | - | ||
1544 | - var r *big.Int | ||
1545 | - ir = new(big.Int) | ||
1546 | - for { | ||
1547 | - r, err = rand.Int(random, priv.N) | ||
1548 | - if err != nil { | ||
1549 | - return | ||
1550 | - } | ||
1551 | - if r.Cmp(bigZero) == 0 { | ||
1552 | - r = bigOne | ||
1553 | - } | ||
1554 | - ok := ir.ModInverse(r, priv.N) | ||
1555 | - if ok != nil { | ||
1556 | - break | ||
1557 | - } | ||
1558 | - } | ||
1559 | - bigE := big.NewInt(int64(priv.E)) | ||
1560 | - rpowe := new(big.Int).Exp(r, bigE, priv.N) // N != 0 | ||
1561 | - cCopy := new(big.Int).Set(c) | ||
1562 | - cCopy.Mul(cCopy, rpowe) | ||
1563 | - cCopy.Mod(cCopy, priv.N) | ||
1564 | - c = cCopy | ||
1565 | - } | ||
1566 | - | ||
1567 | + // Note that because our private decryption exponents are stored as big.Int, | ||
1568 | + // we potentially leak the exact number of bits of these exponents. This | ||
1569 | + // isn't great, but should be fine. | ||
1570 | if priv.Precomputed.Dp == nil { | ||
1571 | - m = new(big.Int).Exp(c, priv.D, priv.N) | ||
1572 | - } else { | ||
1573 | - // We have the precalculated values needed for the CRT. | ||
1574 | - m = new(big.Int).Exp(c, priv.Precomputed.Dp, priv.Primes[0]) | ||
1575 | - m2 := new(big.Int).Exp(c, priv.Precomputed.Dq, priv.Primes[1]) | ||
1576 | - m.Sub(m, m2) | ||
1577 | - if m.Sign() < 0 { | ||
1578 | - m.Add(m, priv.Primes[0]) | ||
1579 | - } | ||
1580 | - m.Mul(m, priv.Precomputed.Qinv) | ||
1581 | - m.Mod(m, priv.Primes[0]) | ||
1582 | - m.Mul(m, priv.Primes[1]) | ||
1583 | - m.Add(m, m2) | ||
1584 | - | ||
1585 | - for i, values := range priv.Precomputed.CRTValues { | ||
1586 | - prime := priv.Primes[2+i] | ||
1587 | - m2.Exp(c, values.Exp, prime) | ||
1588 | - m2.Sub(m2, m) | ||
1589 | - m2.Mul(m2, values.Coeff) | ||
1590 | - m2.Mod(m2, prime) | ||
1591 | - if m2.Sign() < 0 { | ||
1592 | - m2.Add(m2, prime) | ||
1593 | - } | ||
1594 | - m2.Mul(m2, values.R) | ||
1595 | - m.Add(m, m2) | ||
1596 | - } | ||
1597 | - } | ||
1598 | - | ||
1599 | - if ir != nil { | ||
1600 | - // Unblind. | ||
1601 | - m.Mul(m, ir) | ||
1602 | - m.Mod(m, priv.N) | ||
1603 | - } | ||
1604 | - | ||
1605 | - return | ||
1606 | + out := make([]byte, modulusSize(N)) | ||
1607 | + return new(nat).exp(c, priv.D.Bytes(), N).fillBytes(out), nil | ||
1608 | + } | ||
1609 | + | ||
1610 | + t0 := new(nat) | ||
1611 | + P := modulusFromNat(natFromBig(priv.Primes[0])) | ||
1612 | + Q := modulusFromNat(natFromBig(priv.Primes[1])) | ||
1613 | + // m = c ^ Dp mod p | ||
1614 | + m := new(nat).exp(t0.mod(c, P), priv.Precomputed.Dp.Bytes(), P) | ||
1615 | + // m2 = c ^ Dq mod q | ||
1616 | + m2 := new(nat).exp(t0.mod(c, Q), priv.Precomputed.Dq.Bytes(), Q) | ||
1617 | + // m = m - m2 mod p | ||
1618 | + m.modSub(t0.mod(m2, P), P) | ||
1619 | + // m = m * Qinv mod p | ||
1620 | + m.modMul(natFromBig(priv.Precomputed.Qinv).expandFor(P), P) | ||
1621 | + // m = m * q mod N | ||
1622 | + m.expandFor(N).modMul(t0.mod(Q.nat, N), N) | ||
1623 | + // m = m + m2 mod N | ||
1624 | + m.modAdd(m2.expandFor(N), N) | ||
1625 | + | ||
1626 | + for i, values := range priv.Precomputed.CRTValues { | ||
1627 | + p := modulusFromNat(natFromBig(priv.Primes[2+i])) | ||
1628 | + // m2 = c ^ Exp mod p | ||
1629 | + m2.exp(t0.mod(c, p), values.Exp.Bytes(), p) | ||
1630 | + // m2 = m2 - m mod p | ||
1631 | + m2.modSub(t0.mod(m, p), p) | ||
1632 | + // m2 = m2 * Coeff mod p | ||
1633 | + m2.modMul(natFromBig(values.Coeff).expandFor(p), p) | ||
1634 | + // m2 = m2 * R mod N | ||
1635 | + R := natFromBig(values.R).expandFor(N) | ||
1636 | + m2.expandFor(N).modMul(R, N) | ||
1637 | + // m = m + m2 mod N | ||
1638 | + m.modAdd(m2, N) | ||
1639 | + } | ||
1640 | + | ||
1641 | + out := make([]byte, modulusSize(N)) | ||
1642 | + return m.fillBytes(out), nil | ||
1643 | } | ||
1644 | |||
1645 | -func decryptAndCheck(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int, err error) { | ||
1646 | - m, err = decrypt(random, priv, c) | ||
1647 | +func decryptAndCheck(priv *PrivateKey, ciphertext []byte) (m []byte, err error) { | ||
1648 | + m, err = decrypt(priv, ciphertext) | ||
1649 | if err != nil { | ||
1650 | return nil, err | ||
1651 | } | ||
1652 | |||
1653 | // In order to defend against errors in the CRT computation, m^e is | ||
1654 | // calculated, which should match the original ciphertext. | ||
1655 | - check := encrypt(new(big.Int), &priv.PublicKey, m) | ||
1656 | - if c.Cmp(check) != 0 { | ||
1657 | + check := encrypt(&priv.PublicKey, m) | ||
1658 | + if subtle.ConstantTimeCompare(ciphertext, check) != 1 { | ||
1659 | return nil, errors.New("rsa: internal error") | ||
1660 | } | ||
1661 | return m, nil | ||
1662 | @@ -554,9 +534,7 @@ func decryptAndCheck(random io.Reader, priv *PrivateKey, c *big.Int) (m *big.Int | ||
1663 | // Encryption and decryption of a given message must use the same hash function | ||
1664 | // and sha256.New() is a reasonable choice. | ||
1665 | // | ||
1666 | -// The random parameter, if not nil, is used to blind the private-key operation | ||
1667 | -// and avoid timing side-channel attacks. Blinding is purely internal to this | ||
1668 | -// function – the random data need not match that used when encrypting. | ||
1669 | +// The random parameter is legacy and ignored, and it can be as nil. | ||
1670 | // | ||
1671 | // The label parameter must match the value given when encrypting. See | ||
1672 | // EncryptOAEP for details. | ||
1673 | @@ -570,9 +548,7 @@ func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext | ||
1674 | return nil, ErrDecryption | ||
1675 | } | ||
1676 | |||
1677 | - c := new(big.Int).SetBytes(ciphertext) | ||
1678 | - | ||
1679 | - m, err := decrypt(random, priv, c) | ||
1680 | + em, err := decrypt(priv, ciphertext) | ||
1681 | if err != nil { | ||
1682 | return nil, err | ||
1683 | } | ||
1684 | @@ -581,10 +557,6 @@ func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext | ||
1685 | lHash := hash.Sum(nil) | ||
1686 | hash.Reset() | ||
1687 | |||
1688 | - // We probably leak the number of leading zeros. | ||
1689 | - // It's not clear that we can do anything about this. | ||
1690 | - em := m.FillBytes(make([]byte, k)) | ||
1691 | - | ||
1692 | firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0) | ||
1693 | |||
1694 | seed := em[1 : hash.Size()+1] | ||
1695 | -- | ||
1696 | 2.25.1 | ||
1697 | |||