diff options
| -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 | |||
