mirror of
https://git.yoctoproject.org/poky
synced 2026-06-03 01:40:07 +00:00
go: Backport fix for CVE-2023-45287
Upstream-Status: Backport [https://github.com/golang/go/commit/9baafabac9a84813a336f068862207d2bb06d255 & https://github.com/golang/go/commit/c9d5f60eaa4450ccf1ce878d55b4c6a12843f2f3 & https://github.com/golang/go/commit/8f676144ad7b7c91adb0c6e1ec89aaa6283c6807 & https://github.com/golang/go/commit/8a81fdf165facdcefa06531de5af98a4db343035] (From OE-Core rev: 20e1d10a3ebefc8c5237c065c25eba4182d22efd) Signed-off-by: Vijay Anusuri <vanusuri@mvista.com> Signed-off-by: Steve Sakoman <steve@sakoman.com>
This commit is contained in:
committed by
Steve Sakoman
parent
b418ede994
commit
5c5aa47adb
@@ -83,6 +83,10 @@ SRC_URI += "\
|
||||
file://CVE-2023-39318.patch \
|
||||
file://CVE-2023-39319.patch \
|
||||
file://CVE-2023-39326.patch \
|
||||
file://CVE-2023-45287-pre1.patch \
|
||||
file://CVE-2023-45287-pre2.patch \
|
||||
file://CVE-2023-45287-pre3.patch \
|
||||
file://CVE-2023-45287.patch \
|
||||
"
|
||||
|
||||
SRC_URI_append_libc-musl = " file://0009-ld-replace-glibc-dynamic-linker-with-musl.patch"
|
||||
|
||||
@@ -0,0 +1,393 @@
|
||||
From 9baafabac9a84813a336f068862207d2bb06d255 Mon Sep 17 00:00:00 2001
|
||||
From: Filippo Valsorda <filippo@golang.org>
|
||||
Date: Wed, 1 Apr 2020 17:25:40 -0400
|
||||
Subject: [PATCH] crypto/rsa: refactor RSA-PSS signing and verification
|
||||
|
||||
Cleaned up for readability and consistency.
|
||||
|
||||
There is one tiny behavioral change: when PSSSaltLengthEqualsHash is
|
||||
used and both hash and opts.Hash were set, hash.Size() was used for the
|
||||
salt length instead of opts.Hash.Size(). That's clearly wrong because
|
||||
opts.Hash is documented to override hash.
|
||||
|
||||
Change-Id: I3e25dad933961eac827c6d2e3bbfe45fc5a6fb0e
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/226937
|
||||
Run-TryBot: Filippo Valsorda <filippo@golang.org>
|
||||
TryBot-Result: Gobot Gobot <gobot@golang.org>
|
||||
Reviewed-by: Katie Hockman <katie@golang.org>
|
||||
|
||||
Upstream-Status: Backport [https://github.com/golang/go/commit/9baafabac9a84813a336f068862207d2bb06d255]
|
||||
CVE: CVE-2023-45287 #Dependency Patch1
|
||||
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
|
||||
---
|
||||
src/crypto/rsa/pss.go | 173 ++++++++++++++++++++++--------------------
|
||||
src/crypto/rsa/rsa.go | 9 ++-
|
||||
2 files changed, 96 insertions(+), 86 deletions(-)
|
||||
|
||||
diff --git a/src/crypto/rsa/pss.go b/src/crypto/rsa/pss.go
|
||||
index 3ff0c2f4d0076..f9844d87329a8 100644
|
||||
--- a/src/crypto/rsa/pss.go
|
||||
+++ b/src/crypto/rsa/pss.go
|
||||
@@ -4,9 +4,7 @@
|
||||
|
||||
package rsa
|
||||
|
||||
-// This file implements the PSS signature scheme [1].
|
||||
-//
|
||||
-// [1] https://www.emc.com/collateral/white-papers/h11300-pkcs-1v2-2-rsa-cryptography-standard-wp.pdf
|
||||
+// This file implements the RSASSA-PSS signature scheme according to RFC 8017.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -17,8 +15,22 @@ import (
|
||||
"math/big"
|
||||
)
|
||||
|
||||
+// Per RFC 8017, Section 9.1
|
||||
+//
|
||||
+// EM = MGF1 xor DB || H( 8*0x00 || mHash || salt ) || 0xbc
|
||||
+//
|
||||
+// where
|
||||
+//
|
||||
+// DB = PS || 0x01 || salt
|
||||
+//
|
||||
+// and PS can be empty so
|
||||
+//
|
||||
+// emLen = dbLen + hLen + 1 = psLen + sLen + hLen + 2
|
||||
+//
|
||||
+
|
||||
func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byte, error) {
|
||||
- // See [1], section 9.1.1
|
||||
+ // See RFC 8017, Section 9.1.1.
|
||||
+
|
||||
hLen := hash.Size()
|
||||
sLen := len(salt)
|
||||
emLen := (emBits + 7) / 8
|
||||
@@ -30,7 +42,7 @@ func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byt
|
||||
// 2. Let mHash = Hash(M), an octet string of length hLen.
|
||||
|
||||
if len(mHash) != hLen {
|
||||
- return nil, errors.New("crypto/rsa: input must be hashed message")
|
||||
+ return nil, errors.New("crypto/rsa: input must be hashed with given hash")
|
||||
}
|
||||
|
||||
// 3. If emLen < hLen + sLen + 2, output "encoding error" and stop.
|
||||
@@ -40,8 +52,9 @@ func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byt
|
||||
}
|
||||
|
||||
em := make([]byte, emLen)
|
||||
- db := em[:emLen-sLen-hLen-2+1+sLen]
|
||||
- h := em[emLen-sLen-hLen-2+1+sLen : emLen-1]
|
||||
+ psLen := emLen - sLen - hLen - 2
|
||||
+ db := em[:psLen+1+sLen]
|
||||
+ h := em[psLen+1+sLen : emLen-1]
|
||||
|
||||
// 4. Generate a random octet string salt of length sLen; if sLen = 0,
|
||||
// then salt is the empty string.
|
||||
@@ -69,8 +82,8 @@ func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byt
|
||||
// 8. Let DB = PS || 0x01 || salt; DB is an octet string of length
|
||||
// emLen - hLen - 1.
|
||||
|
||||
- db[emLen-sLen-hLen-2] = 0x01
|
||||
- copy(db[emLen-sLen-hLen-1:], salt)
|
||||
+ db[psLen] = 0x01
|
||||
+ copy(db[psLen+1:], salt)
|
||||
|
||||
// 9. Let dbMask = MGF(H, emLen - hLen - 1).
|
||||
//
|
||||
@@ -81,47 +94,57 @@ func emsaPSSEncode(mHash []byte, emBits int, salt []byte, hash hash.Hash) ([]byt
|
||||
// 11. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in
|
||||
// maskedDB to zero.
|
||||
|
||||
- db[0] &= (0xFF >> uint(8*emLen-emBits))
|
||||
+ db[0] &= 0xff >> (8*emLen - emBits)
|
||||
|
||||
// 12. Let EM = maskedDB || H || 0xbc.
|
||||
- em[emLen-1] = 0xBC
|
||||
+ em[emLen-1] = 0xbc
|
||||
|
||||
// 13. Output EM.
|
||||
return em, nil
|
||||
}
|
||||
|
||||
func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error {
|
||||
+ // See RFC 8017, Section 9.1.2.
|
||||
+
|
||||
+ hLen := hash.Size()
|
||||
+ if sLen == PSSSaltLengthEqualsHash {
|
||||
+ sLen = hLen
|
||||
+ }
|
||||
+ emLen := (emBits + 7) / 8
|
||||
+ if emLen != len(em) {
|
||||
+ return errors.New("rsa: internal error: inconsistent length")
|
||||
+ }
|
||||
+
|
||||
// 1. If the length of M is greater than the input limitation for the
|
||||
// hash function (2^61 - 1 octets for SHA-1), output "inconsistent"
|
||||
// and stop.
|
||||
//
|
||||
// 2. Let mHash = Hash(M), an octet string of length hLen.
|
||||
- hLen := hash.Size()
|
||||
if hLen != len(mHash) {
|
||||
return ErrVerification
|
||||
}
|
||||
|
||||
// 3. If emLen < hLen + sLen + 2, output "inconsistent" and stop.
|
||||
- emLen := (emBits + 7) / 8
|
||||
if emLen < hLen+sLen+2 {
|
||||
return ErrVerification
|
||||
}
|
||||
|
||||
// 4. If the rightmost octet of EM does not have hexadecimal value
|
||||
// 0xbc, output "inconsistent" and stop.
|
||||
- if em[len(em)-1] != 0xBC {
|
||||
+ if em[emLen-1] != 0xbc {
|
||||
return ErrVerification
|
||||
}
|
||||
|
||||
// 5. Let maskedDB be the leftmost emLen - hLen - 1 octets of EM, and
|
||||
// let H be the next hLen octets.
|
||||
db := em[:emLen-hLen-1]
|
||||
- h := em[emLen-hLen-1 : len(em)-1]
|
||||
+ h := em[emLen-hLen-1 : emLen-1]
|
||||
|
||||
// 6. If the leftmost 8 * emLen - emBits bits of the leftmost octet in
|
||||
// maskedDB are not all equal to zero, output "inconsistent" and
|
||||
// stop.
|
||||
- if em[0]&(0xFF<<uint(8-(8*emLen-emBits))) != 0 {
|
||||
+ var bitMask byte = 0xff >> (8*emLen - emBits)
|
||||
+ if em[0] & ^bitMask != 0 {
|
||||
return ErrVerification
|
||||
}
|
||||
|
||||
@@ -132,37 +155,30 @@ func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error {
|
||||
|
||||
// 9. Set the leftmost 8 * emLen - emBits bits of the leftmost octet in DB
|
||||
// to zero.
|
||||
- db[0] &= (0xFF >> uint(8*emLen-emBits))
|
||||
+ db[0] &= bitMask
|
||||
|
||||
+ // If we don't know the salt length, look for the 0x01 delimiter.
|
||||
if sLen == PSSSaltLengthAuto {
|
||||
- FindSaltLength:
|
||||
- for sLen = emLen - (hLen + 2); sLen >= 0; sLen-- {
|
||||
- switch db[emLen-hLen-sLen-2] {
|
||||
- case 1:
|
||||
- break FindSaltLength
|
||||
- case 0:
|
||||
- continue
|
||||
- default:
|
||||
- return ErrVerification
|
||||
- }
|
||||
- }
|
||||
- if sLen < 0 {
|
||||
+ psLen := bytes.IndexByte(db, 0x01)
|
||||
+ if psLen < 0 {
|
||||
return ErrVerification
|
||||
}
|
||||
- } else {
|
||||
- // 10. If the emLen - hLen - sLen - 2 leftmost octets of DB are not zero
|
||||
- // or if the octet at position emLen - hLen - sLen - 1 (the leftmost
|
||||
- // position is "position 1") does not have hexadecimal value 0x01,
|
||||
- // output "inconsistent" and stop.
|
||||
- for _, e := range db[:emLen-hLen-sLen-2] {
|
||||
- if e != 0x00 {
|
||||
- return ErrVerification
|
||||
- }
|
||||
- }
|
||||
- if db[emLen-hLen-sLen-2] != 0x01 {
|
||||
+ sLen = len(db) - psLen - 1
|
||||
+ }
|
||||
+
|
||||
+ // 10. If the emLen - hLen - sLen - 2 leftmost octets of DB are not zero
|
||||
+ // or if the octet at position emLen - hLen - sLen - 1 (the leftmost
|
||||
+ // position is "position 1") does not have hexadecimal value 0x01,
|
||||
+ // output "inconsistent" and stop.
|
||||
+ psLen := emLen - hLen - sLen - 2
|
||||
+ for _, e := range db[:psLen] {
|
||||
+ if e != 0x00 {
|
||||
return ErrVerification
|
||||
}
|
||||
}
|
||||
+ if db[psLen] != 0x01 {
|
||||
+ return ErrVerification
|
||||
+ }
|
||||
|
||||
// 11. Let salt be the last sLen octets of DB.
|
||||
salt := db[len(db)-sLen:]
|
||||
@@ -181,19 +197,19 @@ func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error {
|
||||
h0 := hash.Sum(nil)
|
||||
|
||||
// 14. If H = H', output "consistent." Otherwise, output "inconsistent."
|
||||
- if !bytes.Equal(h0, h) {
|
||||
+ if !bytes.Equal(h0, h) { // TODO: constant time?
|
||||
return ErrVerification
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
-// signPSSWithSalt calculates the signature of hashed using PSS [1] with specified salt.
|
||||
+// signPSSWithSalt calculates the signature of hashed using PSS with specified salt.
|
||||
// Note that hashed must be the result of hashing the input message using the
|
||||
// given hash function. salt is a random sequence of bytes whose length will be
|
||||
// later used to verify the signature.
|
||||
func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) (s []byte, err error) {
|
||||
- nBits := priv.N.BitLen()
|
||||
- em, err := emsaPSSEncode(hashed, nBits-1, salt, hash.New())
|
||||
+ emBits := priv.N.BitLen() - 1
|
||||
+ em, err := emsaPSSEncode(hashed, emBits, salt, hash.New())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -202,7 +218,7 @@ func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed,
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
- s = make([]byte, (nBits+7)/8)
|
||||
+ s = make([]byte, priv.Size())
|
||||
copyWithLeftPad(s, c.Bytes())
|
||||
return
|
||||
}
|
||||
@@ -223,16 +239,15 @@ type PSSOptions struct {
|
||||
// PSSSaltLength constants.
|
||||
SaltLength int
|
||||
|
||||
- // Hash, if not zero, overrides the hash function passed to SignPSS.
|
||||
- // This is the only way to specify the hash function when using the
|
||||
- // crypto.Signer interface.
|
||||
+ // Hash is the hash function used to generate the message digest. If not
|
||||
+ // zero, it overrides the hash function passed to SignPSS. It's required
|
||||
+ // when using PrivateKey.Sign.
|
||||
Hash crypto.Hash
|
||||
}
|
||||
|
||||
-// HashFunc returns pssOpts.Hash so that PSSOptions implements
|
||||
-// crypto.SignerOpts.
|
||||
-func (pssOpts *PSSOptions) HashFunc() crypto.Hash {
|
||||
- return pssOpts.Hash
|
||||
+// HashFunc returns opts.Hash so that PSSOptions implements crypto.SignerOpts.
|
||||
+func (opts *PSSOptions) HashFunc() crypto.Hash {
|
||||
+ return opts.Hash
|
||||
}
|
||||
|
||||
func (opts *PSSOptions) saltLength() int {
|
||||
@@ -242,56 +257,50 @@ func (opts *PSSOptions) saltLength() int {
|
||||
return opts.SaltLength
|
||||
}
|
||||
|
||||
-// SignPSS calculates the signature of hashed using RSASSA-PSS [1].
|
||||
-// Note that hashed must be the result of hashing the input message using the
|
||||
-// given hash function. The opts argument may be nil, in which case sensible
|
||||
-// defaults are used.
|
||||
-func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []byte, opts *PSSOptions) ([]byte, error) {
|
||||
+// SignPSS calculates the signature of digest using PSS.
|
||||
+//
|
||||
+// digest must be the result of hashing the input message using the given hash
|
||||
+// function. The opts argument may be nil, in which case sensible defaults are
|
||||
+// used. If opts.Hash is set, it overrides hash.
|
||||
+func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, opts *PSSOptions) ([]byte, error) {
|
||||
+ if opts != nil && opts.Hash != 0 {
|
||||
+ hash = opts.Hash
|
||||
+ }
|
||||
+
|
||||
saltLength := opts.saltLength()
|
||||
switch saltLength {
|
||||
case PSSSaltLengthAuto:
|
||||
- saltLength = (priv.N.BitLen()+7)/8 - 2 - hash.Size()
|
||||
+ saltLength = priv.Size() - 2 - hash.Size()
|
||||
case PSSSaltLengthEqualsHash:
|
||||
saltLength = hash.Size()
|
||||
}
|
||||
|
||||
- if opts != nil && opts.Hash != 0 {
|
||||
- hash = opts.Hash
|
||||
- }
|
||||
-
|
||||
salt := make([]byte, saltLength)
|
||||
if _, err := io.ReadFull(rand, salt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
- return signPSSWithSalt(rand, priv, hash, hashed, salt)
|
||||
+ return signPSSWithSalt(rand, priv, hash, digest, salt)
|
||||
}
|
||||
|
||||
// VerifyPSS verifies a PSS signature.
|
||||
-// hashed is the result of hashing the input message using the given hash
|
||||
-// function and sig is the signature. A valid signature is indicated by
|
||||
-// returning a nil error. The opts argument may be nil, in which case sensible
|
||||
-// defaults are used.
|
||||
-func VerifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, opts *PSSOptions) error {
|
||||
- return verifyPSS(pub, hash, hashed, sig, opts.saltLength())
|
||||
-}
|
||||
-
|
||||
-// verifyPSS verifies a PSS signature with the given salt length.
|
||||
-func verifyPSS(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte, saltLen int) error {
|
||||
- nBits := pub.N.BitLen()
|
||||
- if len(sig) != (nBits+7)/8 {
|
||||
+//
|
||||
+// A valid signature is indicated by returning a nil error. digest must be the
|
||||
+// result of hashing the input message using the given hash function. The opts
|
||||
+// argument may be nil, in which case sensible defaults are used. opts.Hash is
|
||||
+// ignored.
|
||||
+func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts *PSSOptions) error {
|
||||
+ if len(sig) != pub.Size() {
|
||||
return ErrVerification
|
||||
}
|
||||
s := new(big.Int).SetBytes(sig)
|
||||
m := encrypt(new(big.Int), pub, s)
|
||||
- emBits := nBits - 1
|
||||
+ emBits := pub.N.BitLen() - 1
|
||||
emLen := (emBits + 7) / 8
|
||||
- if emLen < len(m.Bytes()) {
|
||||
+ emBytes := m.Bytes()
|
||||
+ if emLen < len(emBytes) {
|
||||
return ErrVerification
|
||||
}
|
||||
em := make([]byte, emLen)
|
||||
- copyWithLeftPad(em, m.Bytes())
|
||||
- if saltLen == PSSSaltLengthEqualsHash {
|
||||
- saltLen = hash.Size()
|
||||
- }
|
||||
- return emsaPSSVerify(hashed, em, emBits, saltLen, hash.New())
|
||||
+ copyWithLeftPad(em, emBytes)
|
||||
+ return emsaPSSVerify(digest, em, emBits, opts.saltLength(), hash.New())
|
||||
}
|
||||
diff --git a/src/crypto/rsa/rsa.go b/src/crypto/rsa/rsa.go
|
||||
index 5a42990640164..b4bfa13defbdf 100644
|
||||
--- a/src/crypto/rsa/rsa.go
|
||||
+++ b/src/crypto/rsa/rsa.go
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
-// Package rsa implements RSA encryption as specified in PKCS#1.
|
||||
+// Package rsa implements RSA encryption as specified in PKCS#1 and RFC 8017.
|
||||
//
|
||||
// RSA is a single, fundamental operation that is used in this package to
|
||||
// implement either public-key encryption or public-key signatures.
|
||||
@@ -10,13 +10,13 @@
|
||||
// The original specification for encryption and signatures with RSA is PKCS#1
|
||||
// and the terms "RSA encryption" and "RSA signatures" by default refer to
|
||||
// PKCS#1 version 1.5. However, that specification has flaws and new designs
|
||||
-// should use version two, usually called by just OAEP and PSS, where
|
||||
+// should use version 2, usually called by just OAEP and PSS, where
|
||||
// possible.
|
||||
//
|
||||
// Two sets of interfaces are included in this package. When a more abstract
|
||||
// interface isn't necessary, there are functions for encrypting/decrypting
|
||||
// with v1.5/OAEP and signing/verifying with v1.5/PSS. If one needs to abstract
|
||||
-// over the public-key primitive, the PrivateKey struct implements the
|
||||
+// over the public key primitive, the PrivateKey type implements the
|
||||
// Decrypter and Signer interfaces from the crypto package.
|
||||
//
|
||||
// The RSA operations in this package are not implemented using constant-time algorithms.
|
||||
@@ -111,7 +111,8 @@ func (priv *PrivateKey) Public() crypto.PublicKey {
|
||||
|
||||
// Sign signs digest with priv, reading randomness from rand. If opts is a
|
||||
// *PSSOptions then the PSS algorithm will be used, otherwise PKCS#1 v1.5 will
|
||||
-// be used.
|
||||
+// be used. digest must be the result of hashing the input message using
|
||||
+// opts.HashFunc().
|
||||
//
|
||||
// This method implements crypto.Signer, which is an interface to support keys
|
||||
// where the private part is kept in, for example, a hardware module. Common
|
||||
@@ -0,0 +1,401 @@
|
||||
From c9d5f60eaa4450ccf1ce878d55b4c6a12843f2f3 Mon Sep 17 00:00:00 2001
|
||||
From: Filippo Valsorda <filippo@golang.org>
|
||||
Date: Mon, 27 Apr 2020 21:52:38 -0400
|
||||
Subject: [PATCH] math/big: add (*Int).FillBytes
|
||||
|
||||
Replaced almost every use of Bytes with FillBytes.
|
||||
|
||||
Note that the approved proposal was for
|
||||
|
||||
func (*Int) FillBytes(buf []byte)
|
||||
|
||||
while this implements
|
||||
|
||||
func (*Int) FillBytes(buf []byte) []byte
|
||||
|
||||
because the latter was far nicer to use in all callsites.
|
||||
|
||||
Fixes #35833
|
||||
|
||||
Change-Id: Ia912df123e5d79b763845312ea3d9a8051343c0a
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/230397
|
||||
Reviewed-by: Robert Griesemer <gri@golang.org>
|
||||
|
||||
Upstream-Status: Backport [https://github.com/golang/go/commit/c9d5f60eaa4450ccf1ce878d55b4c6a12843f2f3]
|
||||
CVE: CVE-2023-45287 #Dependency Patch2
|
||||
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
|
||||
---
|
||||
src/crypto/elliptic/elliptic.go | 13 ++++----
|
||||
src/crypto/rsa/pkcs1v15.go | 20 +++---------
|
||||
src/crypto/rsa/pss.go | 17 +++++------
|
||||
src/crypto/rsa/rsa.go | 32 +++----------------
|
||||
src/crypto/tls/key_schedule.go | 7 ++---
|
||||
src/crypto/x509/sec1.go | 7 ++---
|
||||
src/math/big/int.go | 15 +++++++++
|
||||
src/math/big/int_test.go | 54 +++++++++++++++++++++++++++++++++
|
||||
src/math/big/nat.go | 15 ++++++---
|
||||
9 files changed, 106 insertions(+), 74 deletions(-)
|
||||
|
||||
diff --git a/src/crypto/elliptic/elliptic.go b/src/crypto/elliptic/elliptic.go
|
||||
index e2f71cdb63bab..bd5168c5fd842 100644
|
||||
--- a/src/crypto/elliptic/elliptic.go
|
||||
+++ b/src/crypto/elliptic/elliptic.go
|
||||
@@ -277,7 +277,7 @@ var mask = []byte{0xff, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f}
|
||||
func GenerateKey(curve Curve, rand io.Reader) (priv []byte, x, y *big.Int, err error) {
|
||||
N := curve.Params().N
|
||||
bitSize := N.BitLen()
|
||||
- byteLen := (bitSize + 7) >> 3
|
||||
+ byteLen := (bitSize + 7) / 8
|
||||
priv = make([]byte, byteLen)
|
||||
|
||||
for x == nil {
|
||||
@@ -304,15 +304,14 @@ func GenerateKey(curve Curve, rand io.Reader) (priv []byte, x, y *big.Int, err e
|
||||
|
||||
// Marshal converts a point into the uncompressed form specified in section 4.3.6 of ANSI X9.62.
|
||||
func Marshal(curve Curve, x, y *big.Int) []byte {
|
||||
- byteLen := (curve.Params().BitSize + 7) >> 3
|
||||
+ byteLen := (curve.Params().BitSize + 7) / 8
|
||||
|
||||
ret := make([]byte, 1+2*byteLen)
|
||||
ret[0] = 4 // uncompressed point
|
||||
|
||||
- xBytes := x.Bytes()
|
||||
- copy(ret[1+byteLen-len(xBytes):], xBytes)
|
||||
- yBytes := y.Bytes()
|
||||
- copy(ret[1+2*byteLen-len(yBytes):], yBytes)
|
||||
+ x.FillBytes(ret[1 : 1+byteLen])
|
||||
+ y.FillBytes(ret[1+byteLen : 1+2*byteLen])
|
||||
+
|
||||
return ret
|
||||
}
|
||||
|
||||
@@ -320,7 +319,7 @@ func Marshal(curve Curve, x, y *big.Int) []byte {
|
||||
// It is an error if the point is not in uncompressed form or is not on the curve.
|
||||
// On error, x = nil.
|
||||
func Unmarshal(curve Curve, data []byte) (x, y *big.Int) {
|
||||
- byteLen := (curve.Params().BitSize + 7) >> 3
|
||||
+ byteLen := (curve.Params().BitSize + 7) / 8
|
||||
if len(data) != 1+2*byteLen {
|
||||
return
|
||||
}
|
||||
diff --git a/src/crypto/rsa/pkcs1v15.go b/src/crypto/rsa/pkcs1v15.go
|
||||
index 499242ffc5b57..3208119ae1ff4 100644
|
||||
--- a/src/crypto/rsa/pkcs1v15.go
|
||||
+++ b/src/crypto/rsa/pkcs1v15.go
|
||||
@@ -61,8 +61,7 @@ func EncryptPKCS1v15(rand io.Reader, pub *PublicKey, msg []byte) ([]byte, error)
|
||||
m := new(big.Int).SetBytes(em)
|
||||
c := encrypt(new(big.Int), pub, m)
|
||||
|
||||
- copyWithLeftPad(em, c.Bytes())
|
||||
- return em, nil
|
||||
+ return c.FillBytes(em), nil
|
||||
}
|
||||
|
||||
// DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from PKCS#1 v1.5.
|
||||
@@ -150,7 +149,7 @@ func decryptPKCS1v15(rand io.Reader, priv *PrivateKey, ciphertext []byte) (valid
|
||||
return
|
||||
}
|
||||
|
||||
- em = leftPad(m.Bytes(), k)
|
||||
+ em = m.FillBytes(make([]byte, k))
|
||||
firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0)
|
||||
secondByteIsTwo := subtle.ConstantTimeByteEq(em[1], 2)
|
||||
|
||||
@@ -256,8 +255,7 @@ func SignPKCS1v15(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed []b
|
||||
return nil, err
|
||||
}
|
||||
|
||||
- copyWithLeftPad(em, c.Bytes())
|
||||
- return em, nil
|
||||
+ return c.FillBytes(em), nil
|
||||
}
|
||||
|
||||
// VerifyPKCS1v15 verifies an RSA PKCS#1 v1.5 signature.
|
||||
@@ -286,7 +284,7 @@ func VerifyPKCS1v15(pub *PublicKey, hash crypto.Hash, hashed []byte, sig []byte)
|
||||
|
||||
c := new(big.Int).SetBytes(sig)
|
||||
m := encrypt(new(big.Int), pub, c)
|
||||
- em := leftPad(m.Bytes(), k)
|
||||
+ em := m.FillBytes(make([]byte, k))
|
||||
// EM = 0x00 || 0x01 || PS || 0x00 || T
|
||||
|
||||
ok := subtle.ConstantTimeByteEq(em[0], 0)
|
||||
@@ -323,13 +321,3 @@ func pkcs1v15HashInfo(hash crypto.Hash, inLen int) (hashLen int, prefix []byte,
|
||||
}
|
||||
return
|
||||
}
|
||||
-
|
||||
-// copyWithLeftPad copies src to the end of dest, padding with zero bytes as
|
||||
-// needed.
|
||||
-func copyWithLeftPad(dest, src []byte) {
|
||||
- numPaddingBytes := len(dest) - len(src)
|
||||
- for i := 0; i < numPaddingBytes; i++ {
|
||||
- dest[i] = 0
|
||||
- }
|
||||
- copy(dest[numPaddingBytes:], src)
|
||||
-}
|
||||
diff --git a/src/crypto/rsa/pss.go b/src/crypto/rsa/pss.go
|
||||
index f9844d87329a8..b2adbedb28fa8 100644
|
||||
--- a/src/crypto/rsa/pss.go
|
||||
+++ b/src/crypto/rsa/pss.go
|
||||
@@ -207,20 +207,19 @@ func emsaPSSVerify(mHash, em []byte, emBits, sLen int, hash hash.Hash) error {
|
||||
// Note that hashed must be the result of hashing the input message using the
|
||||
// given hash function. salt is a random sequence of bytes whose length will be
|
||||
// later used to verify the signature.
|
||||
-func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) (s []byte, err error) {
|
||||
+func signPSSWithSalt(rand io.Reader, priv *PrivateKey, hash crypto.Hash, hashed, salt []byte) ([]byte, error) {
|
||||
emBits := priv.N.BitLen() - 1
|
||||
em, err := emsaPSSEncode(hashed, emBits, salt, hash.New())
|
||||
if err != nil {
|
||||
- return
|
||||
+ return nil, err
|
||||
}
|
||||
m := new(big.Int).SetBytes(em)
|
||||
c, err := decryptAndCheck(rand, priv, m)
|
||||
if err != nil {
|
||||
- return
|
||||
+ return nil, err
|
||||
}
|
||||
- s = make([]byte, priv.Size())
|
||||
- copyWithLeftPad(s, c.Bytes())
|
||||
- return
|
||||
+ s := make([]byte, priv.Size())
|
||||
+ return c.FillBytes(s), nil
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -296,11 +295,9 @@ func VerifyPSS(pub *PublicKey, hash crypto.Hash, digest []byte, sig []byte, opts
|
||||
m := encrypt(new(big.Int), pub, s)
|
||||
emBits := pub.N.BitLen() - 1
|
||||
emLen := (emBits + 7) / 8
|
||||
- emBytes := m.Bytes()
|
||||
- if emLen < len(emBytes) {
|
||||
+ if m.BitLen() > emLen*8 {
|
||||
return ErrVerification
|
||||
}
|
||||
- em := make([]byte, emLen)
|
||||
- copyWithLeftPad(em, emBytes)
|
||||
+ em := m.FillBytes(make([]byte, emLen))
|
||||
return emsaPSSVerify(digest, em, emBits, opts.saltLength(), hash.New())
|
||||
}
|
||||
diff --git a/src/crypto/rsa/rsa.go b/src/crypto/rsa/rsa.go
|
||||
index b4bfa13defbdf..28eb5926c1a54 100644
|
||||
--- a/src/crypto/rsa/rsa.go
|
||||
+++ b/src/crypto/rsa/rsa.go
|
||||
@@ -416,16 +416,9 @@ func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, l
|
||||
m := new(big.Int)
|
||||
m.SetBytes(em)
|
||||
c := encrypt(new(big.Int), pub, m)
|
||||
- out := c.Bytes()
|
||||
|
||||
- if len(out) < k {
|
||||
- // If the output is too small, we need to left-pad with zeros.
|
||||
- t := make([]byte, k)
|
||||
- copy(t[k-len(out):], out)
|
||||
- out = t
|
||||
- }
|
||||
-
|
||||
- return out, nil
|
||||
+ out := make([]byte, k)
|
||||
+ return c.FillBytes(out), nil
|
||||
}
|
||||
|
||||
// ErrDecryption represents a failure to decrypt a message.
|
||||
@@ -597,12 +590,9 @@ func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext
|
||||
lHash := hash.Sum(nil)
|
||||
hash.Reset()
|
||||
|
||||
- // Converting the plaintext number to bytes will strip any
|
||||
- // leading zeros so we may have to left pad. We do this unconditionally
|
||||
- // to avoid leaking timing information. (Although we still probably
|
||||
- // leak the number of leading zeros. It's not clear that we can do
|
||||
- // anything about this.)
|
||||
- em := leftPad(m.Bytes(), k)
|
||||
+ // We probably leak the number of leading zeros.
|
||||
+ // It's not clear that we can do anything about this.
|
||||
+ em := m.FillBytes(make([]byte, k))
|
||||
|
||||
firstByteIsZero := subtle.ConstantTimeByteEq(em[0], 0)
|
||||
|
||||
@@ -643,15 +633,3 @@ func DecryptOAEP(hash hash.Hash, random io.Reader, priv *PrivateKey, ciphertext
|
||||
|
||||
return rest[index+1:], nil
|
||||
}
|
||||
-
|
||||
-// leftPad returns a new slice of length size. The contents of input are right
|
||||
-// aligned in the new slice.
|
||||
-func leftPad(input []byte, size int) (out []byte) {
|
||||
- n := len(input)
|
||||
- if n > size {
|
||||
- n = size
|
||||
- }
|
||||
- out = make([]byte, size)
|
||||
- copy(out[len(out)-n:], input)
|
||||
- return
|
||||
-}
|
||||
diff --git a/src/crypto/tls/key_schedule.go b/src/crypto/tls/key_schedule.go
|
||||
index 2aab323202f7d..314016979afb8 100644
|
||||
--- a/src/crypto/tls/key_schedule.go
|
||||
+++ b/src/crypto/tls/key_schedule.go
|
||||
@@ -173,11 +173,8 @@ func (p *nistParameters) SharedKey(peerPublicKey []byte) []byte {
|
||||
}
|
||||
|
||||
xShared, _ := curve.ScalarMult(x, y, p.privateKey)
|
||||
- sharedKey := make([]byte, (curve.Params().BitSize+7)>>3)
|
||||
- xBytes := xShared.Bytes()
|
||||
- copy(sharedKey[len(sharedKey)-len(xBytes):], xBytes)
|
||||
-
|
||||
- return sharedKey
|
||||
+ sharedKey := make([]byte, (curve.Params().BitSize+7)/8)
|
||||
+ return xShared.FillBytes(sharedKey)
|
||||
}
|
||||
|
||||
type x25519Parameters struct {
|
||||
diff --git a/src/crypto/x509/sec1.go b/src/crypto/x509/sec1.go
|
||||
index 0bfb90cd5464a..52c108ff1d624 100644
|
||||
--- a/src/crypto/x509/sec1.go
|
||||
+++ b/src/crypto/x509/sec1.go
|
||||
@@ -52,13 +52,10 @@ func MarshalECPrivateKey(key *ecdsa.PrivateKey) ([]byte, error) {
|
||||
// marshalECPrivateKey marshals an EC private key into ASN.1, DER format and
|
||||
// sets the curve ID to the given OID, or omits it if OID is nil.
|
||||
func marshalECPrivateKeyWithOID(key *ecdsa.PrivateKey, oid asn1.ObjectIdentifier) ([]byte, error) {
|
||||
- privateKeyBytes := key.D.Bytes()
|
||||
- paddedPrivateKey := make([]byte, (key.Curve.Params().N.BitLen()+7)/8)
|
||||
- copy(paddedPrivateKey[len(paddedPrivateKey)-len(privateKeyBytes):], privateKeyBytes)
|
||||
-
|
||||
+ privateKey := make([]byte, (key.Curve.Params().N.BitLen()+7)/8)
|
||||
return asn1.Marshal(ecPrivateKey{
|
||||
Version: 1,
|
||||
- PrivateKey: paddedPrivateKey,
|
||||
+ PrivateKey: key.D.FillBytes(privateKey),
|
||||
NamedCurveOID: oid,
|
||||
PublicKey: asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)},
|
||||
})
|
||||
diff --git a/src/math/big/int.go b/src/math/big/int.go
|
||||
index 8816cf5266cc4..65f32487b58c0 100644
|
||||
--- a/src/math/big/int.go
|
||||
+++ b/src/math/big/int.go
|
||||
@@ -447,11 +447,26 @@ func (z *Int) SetBytes(buf []byte) *Int {
|
||||
}
|
||||
|
||||
// Bytes returns the absolute value of x as a big-endian byte slice.
|
||||
+//
|
||||
+// To use a fixed length slice, or a preallocated one, use FillBytes.
|
||||
func (x *Int) Bytes() []byte {
|
||||
buf := make([]byte, len(x.abs)*_S)
|
||||
return buf[x.abs.bytes(buf):]
|
||||
}
|
||||
|
||||
+// FillBytes sets buf to the absolute value of x, storing it as a zero-extended
|
||||
+// big-endian byte slice, and returns buf.
|
||||
+//
|
||||
+// If the absolute value of x doesn't fit in buf, FillBytes will panic.
|
||||
+func (x *Int) FillBytes(buf []byte) []byte {
|
||||
+ // Clear whole buffer. (This gets optimized into a memclr.)
|
||||
+ for i := range buf {
|
||||
+ buf[i] = 0
|
||||
+ }
|
||||
+ x.abs.bytes(buf)
|
||||
+ return buf
|
||||
+}
|
||||
+
|
||||
// BitLen returns the length of the absolute value of x in bits.
|
||||
// The bit length of 0 is 0.
|
||||
func (x *Int) BitLen() int {
|
||||
diff --git a/src/math/big/int_test.go b/src/math/big/int_test.go
|
||||
index e3a1587b3f0ad..3c8557323a032 100644
|
||||
--- a/src/math/big/int_test.go
|
||||
+++ b/src/math/big/int_test.go
|
||||
@@ -1840,3 +1840,57 @@ func BenchmarkDiv(b *testing.B) {
|
||||
})
|
||||
}
|
||||
}
|
||||
+
|
||||
+func TestFillBytes(t *testing.T) {
|
||||
+ checkResult := func(t *testing.T, buf []byte, want *Int) {
|
||||
+ t.Helper()
|
||||
+ got := new(Int).SetBytes(buf)
|
||||
+ if got.CmpAbs(want) != 0 {
|
||||
+ t.Errorf("got 0x%x, want 0x%x: %x", got, want, buf)
|
||||
+ }
|
||||
+ }
|
||||
+ panics := func(f func()) (panic bool) {
|
||||
+ defer func() { panic = recover() != nil }()
|
||||
+ f()
|
||||
+ return
|
||||
+ }
|
||||
+
|
||||
+ for _, n := range []string{
|
||||
+ "0",
|
||||
+ "1000",
|
||||
+ "0xffffffff",
|
||||
+ "-0xffffffff",
|
||||
+ "0xffffffffffffffff",
|
||||
+ "0x10000000000000000",
|
||||
+ "0xabababababababababababababababababababababababababa",
|
||||
+ "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
+ } {
|
||||
+ t.Run(n, func(t *testing.T) {
|
||||
+ t.Logf(n)
|
||||
+ x, ok := new(Int).SetString(n, 0)
|
||||
+ if !ok {
|
||||
+ panic("invalid test entry")
|
||||
+ }
|
||||
+
|
||||
+ // Perfectly sized buffer.
|
||||
+ byteLen := (x.BitLen() + 7) / 8
|
||||
+ buf := make([]byte, byteLen)
|
||||
+ checkResult(t, x.FillBytes(buf), x)
|
||||
+
|
||||
+ // Way larger, checking all bytes get zeroed.
|
||||
+ buf = make([]byte, 100)
|
||||
+ for i := range buf {
|
||||
+ buf[i] = 0xff
|
||||
+ }
|
||||
+ checkResult(t, x.FillBytes(buf), x)
|
||||
+
|
||||
+ // Too small.
|
||||
+ if byteLen > 0 {
|
||||
+ buf = make([]byte, byteLen-1)
|
||||
+ if !panics(func() { x.FillBytes(buf) }) {
|
||||
+ t.Errorf("expected panic for small buffer and value %x", x)
|
||||
+ }
|
||||
+ }
|
||||
+ })
|
||||
+ }
|
||||
+}
|
||||
diff --git a/src/math/big/nat.go b/src/math/big/nat.go
|
||||
index c31ec5156b81d..6a3989bf9d82b 100644
|
||||
--- a/src/math/big/nat.go
|
||||
+++ b/src/math/big/nat.go
|
||||
@@ -1476,19 +1476,26 @@ func (z nat) expNNMontgomery(x, y, m nat) nat {
|
||||
}
|
||||
|
||||
// bytes writes the value of z into buf using big-endian encoding.
|
||||
-// len(buf) must be >= len(z)*_S. The value of z is encoded in the
|
||||
-// slice buf[i:]. The number i of unused bytes at the beginning of
|
||||
-// buf is returned as result.
|
||||
+// The value of z is encoded in the slice buf[i:]. If the value of z
|
||||
+// cannot be represented in buf, bytes panics. The number i of unused
|
||||
+// bytes at the beginning of buf is returned as result.
|
||||
func (z nat) bytes(buf []byte) (i int) {
|
||||
i = len(buf)
|
||||
for _, d := range z {
|
||||
for j := 0; j < _S; j++ {
|
||||
i--
|
||||
- buf[i] = byte(d)
|
||||
+ if i >= 0 {
|
||||
+ buf[i] = byte(d)
|
||||
+ } else if byte(d) != 0 {
|
||||
+ panic("math/big: buffer too small to fit value")
|
||||
+ }
|
||||
d >>= 8
|
||||
}
|
||||
}
|
||||
|
||||
+ if i < 0 {
|
||||
+ i = 0
|
||||
+ }
|
||||
for i < len(buf) && buf[i] == 0 {
|
||||
i++
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
From 8f676144ad7b7c91adb0c6e1ec89aaa6283c6807 Mon Sep 17 00:00:00 2001
|
||||
From: Himanshu Kishna Srivastava <28himanshu@gmail.com>
|
||||
Date: Tue, 16 Mar 2021 22:37:46 +0530
|
||||
Subject: [PATCH] crypto/rsa: fix salt length calculation with
|
||||
PSSSaltLengthAuto
|
||||
|
||||
When PSSSaltLength is set, the maximum salt length must equal:
|
||||
|
||||
(modulus_key_size - 1 + 7)/8 - hash_length - 2
|
||||
and for example, with a 4096 bit modulus key, and a SHA-1 hash,
|
||||
it should be:
|
||||
|
||||
(4096 -1 + 7)/8 - 20 - 2 = 490
|
||||
Previously we'd encounter this error:
|
||||
|
||||
crypto/rsa: key size too small for PSS signature
|
||||
|
||||
Fixes #42741
|
||||
|
||||
Change-Id: I18bb82c41c511d564b3f4c443f4b3a38ab010ac5
|
||||
Reviewed-on: https://go-review.googlesource.com/c/go/+/302230
|
||||
Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
|
||||
Reviewed-by: Filippo Valsorda <filippo@golang.org>
|
||||
Trust: Emmanuel Odeke <emmanuel@orijtech.com>
|
||||
Run-TryBot: Emmanuel Odeke <emmanuel@orijtech.com>
|
||||
TryBot-Result: Go Bot <gobot@golang.org>
|
||||
|
||||
Upstream-Status: Backport [https://github.com/golang/go/commit/8f676144ad7b7c91adb0c6e1ec89aaa6283c6807]
|
||||
CVE: CVE-2023-45287 #Dependency Patch3
|
||||
Signed-off-by: Vijay Anusuri <vanusuri@mvista.com>
|
||||
---
|
||||
src/crypto/rsa/pss.go | 2 +-
|
||||
src/crypto/rsa/pss_test.go | 20 +++++++++++++++++++-
|
||||
2 files changed, 20 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/src/crypto/rsa/pss.go b/src/crypto/rsa/pss.go
|
||||
index b2adbedb28fa8..814522de8181f 100644
|
||||
--- a/src/crypto/rsa/pss.go
|
||||
+++ b/src/crypto/rsa/pss.go
|
||||
@@ -269,7 +269,7 @@ func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte,
|
||||
saltLength := opts.saltLength()
|
||||
switch saltLength {
|
||||
case PSSSaltLengthAuto:
|
||||
- saltLength = priv.Size() - 2 - hash.Size()
|
||||
+ saltLength = (priv.N.BitLen()-1+7)/8 - 2 - hash.Size()
|
||||
case PSSSaltLengthEqualsHash:
|
||||
saltLength = hash.Size()
|
||||
}
|
||||
diff --git a/src/crypto/rsa/pss_test.go b/src/crypto/rsa/pss_test.go
|
||||
index dfa8d8bb5ad02..c3a6d468497cd 100644
|
||||
--- a/src/crypto/rsa/pss_test.go
|
||||
+++ b/src/crypto/rsa/pss_test.go
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
_ "crypto/md5"
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
- _ "crypto/sha256"
|
||||
+ "crypto/sha256"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"os"
|
||||
@@ -233,6 +233,24 @@ func TestPSSSigning(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
+func TestSignWithPSSSaltLengthAuto(t *testing.T) {
|
||||
+ key, err := GenerateKey(rand.Reader, 513)
|
||||
+ if err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+ digest := sha256.Sum256([]byte("message"))
|
||||
+ signature, err := key.Sign(rand.Reader, digest[:], &PSSOptions{
|
||||
+ SaltLength: PSSSaltLengthAuto,
|
||||
+ Hash: crypto.SHA256,
|
||||
+ })
|
||||
+ if err != nil {
|
||||
+ t.Fatal(err)
|
||||
+ }
|
||||
+ if len(signature) == 0 {
|
||||
+ t.Fatal("empty signature returned")
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
func bigFromHex(hex string) *big.Int {
|
||||
n, ok := new(big.Int).SetString(hex, 16)
|
||||
if !ok {
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user