]> Cypherpunks.ru repositories - gostls13.git/commitdiff
[dev.boringcrypto] all: merge master (nearly Go 1.10 beta 1) into dev.boringcrypto
authorRuss Cox <rsc@golang.org>
Wed, 6 Dec 2017 05:35:28 +0000 (00:35 -0500)
committerRuss Cox <rsc@golang.org>
Wed, 6 Dec 2017 06:03:36 +0000 (01:03 -0500)
This is a git merge of master into dev.boringcrypto.

The branch was previously based on release-branch.go1.9,
so there are a handful of spurious conflicts that would
also arise if trying to merge master into release-branch.go1.9
(which we never do). Those have all been resolved by taking
the original file from master, discarding any Go 1.9-specific
edits.

all.bash passes on darwin/amd64, which is to say without
actually using BoringCrypto.

Go 1.10-related fixes to BoringCrypto itself will be in a followup CL.
This CL is just the merge.

Change-Id: I4c97711fec0fb86761913dcde28d25c001246c35

27 files changed:
1  2 
src/cmd/compile/internal/gc/reflect.go
src/cmd/go/go_test.go
src/cmd/go/internal/load/pkg.go
src/cmd/link/internal/ld/lib.go
src/crypto/ecdsa/ecdsa.go
src/crypto/hmac/hmac.go
src/crypto/issue21104_test.go
src/crypto/rsa/pss.go
src/crypto/rsa/rsa.go
src/crypto/sha1/sha1.go
src/crypto/sha1/sha1_test.go
src/crypto/sha256/sha256.go
src/crypto/sha256/sha256_test.go
src/crypto/sha512/sha512.go
src/crypto/sha512/sha512_test.go
src/crypto/tls/boring.go
src/crypto/tls/boring_test.go
src/crypto/tls/common.go
src/crypto/tls/handshake_client.go
src/crypto/tls/handshake_messages_test.go
src/crypto/tls/handshake_server.go
src/crypto/tls/key_agreement.go
src/crypto/tls/prf.go
src/crypto/x509/verify.go
src/go/build/deps_test.go
src/runtime/race/testdata/mop_test.go
src/runtime/runtime_boring.go

index 47ac54182285436dcc237db1811939721460fad5,66b1a8e1861c9f56b45bb2a7e139c11844bca93c..bbb263ee8d39d3548f70475fb2bd6449f073eec2
@@@ -1275,47 -1339,20 +1339,47 @@@ func dtypesym(t *types.Type) *obj.LSym 
        // ../../../../runtime/type.go:/structType
        // for security, only the exported fields.
        case TSTRUCT:
-               n := 0
-               for _, t1 := range t.Fields().Slice() {
-                       if omitFieldForAwfulBoringCryptoKludge(t1) {
-                               continue
+               fields := t.Fields().Slice()
 +
 +              // omitFieldForAwfulBoringCryptoKludge reports whether
 +              // the field t should be omitted from the reflect data.
 +              // In the crypto/... packages we omit an unexported field
 +              // named "boring", to keep from breaking client code that
 +              // expects rsa.PublicKey etc to have only public fields.
 +              // As the name suggests, this is an awful kludge, but it is
 +              // limited to the dev.boringcrypto branch and avoids
 +              // much more invasive effects elsewhere.
 +              omitFieldForAwfulBoringCryptoKludge := func(t *types.Field) bool {
 +                      if t.Sym == nil || t.Sym.Name != "boring" || t.Sym.Pkg == nil {
 +                              return false
 +                      }
 +                      path := t.Sym.Pkg.Path
 +                      if t.Sym.Pkg == localpkg {
 +                              path = myimportpath
 +                      }
 +                      return strings.HasPrefix(path, "crypto/")
 +              }
++              newFields := fields[:0:0]
++              for _, t1 := range fields {
++                      if !omitFieldForAwfulBoringCryptoKludge(t1) {
++                              newFields = append(newFields, t1)
 +                      }
++              }
++              fields = newFields
++
+               for _, t1 := range fields {
                        dtypesym(t1.Type)
-                       n++
                }
  
-               ot = dcommontype(lsym, ot, t)
-               pkg := localpkg
-               if t.Sym != nil {
-                       pkg = t.Sym.Pkg
-               } else {
-                       // Unnamed type. Grab the package from the first field, if any.
-                       for _, f := range t.Fields().Slice() {
-                               if f.Embedded != 0 {
-                                       continue
-                               }
-                               pkg = f.Sym.Pkg
+               // All non-exported struct field names within a struct
+               // type must originate from a single package. By
+               // identifying and recording that package within the
+               // struct type descriptor, we can omit that
+               // information from the field descriptors.
+               var spkg *types.Pkg
+               for _, f := range fields {
+                       if !exportname(f.Sym.Name) {
+                               spkg = f.Sym.Pkg
                                break
                        }
                }
index a12df2988c701544f46bc39eabf07e22b9873b74,e0ac90dddfc49cab7698bbfa86b284cdcf2c4c24..75d65b7235a67ed2e733075ad277fd94284965f2
@@@ -3632,8 -3961,8 +3961,12 @@@ func TestBinaryOnlyPackages(t *testing.
        tg.grepStdout("false", "did not see BinaryOnly=false for p4")
  }
  
 -// Issue 16050.
 -func TestAlwaysLinkSysoFiles(t *testing.T) {
 +// Issue 16050 and 21884.
 +func TestLinkSysoFiles(t *testing.T) {
++      if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" {
++              t.Skip("not linux/amd64")
++      }
++
        tg := testgo(t)
        defer tg.cleanup()
        tg.parallel()
Simple merge
Simple merge
index 3fe1dda660a57d2d18e332bbc43358540b07d783,755ed284a910b8c6093f5507cbbd00d697b35ffc..6a47cc7d98d062e3d702f0817acbf22e2f1168e9
@@@ -49,11 -47,9 +49,11 @@@ const 
  type PublicKey struct {
        elliptic.Curve
        X, Y *big.Int
 +
 +      boring unsafe.Pointer
  }
  
- // PrivateKey represents a ECDSA private key.
+ // PrivateKey represents an ECDSA private key.
  type PrivateKey struct {
        PublicKey
        D *big.Int
@@@ -70,21 -64,15 +70,24 @@@ func (priv *PrivateKey) Public() crypto
        return &priv.PublicKey
  }
  
- // Sign signs msg with priv, reading randomness from rand. This method is
- // intended to support keys where the private part is kept in, for example, a
- // hardware module. Common uses should use the Sign function in this package
- // directly.
- func (priv *PrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) ([]byte, error) {
+ // Sign signs digest with priv, reading randomness from rand. The opts argument
+ // is not currently used but, in keeping with the crypto.Signer interface,
+ // should be the hash function used to digest the message.
+ //
+ // 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
+ // uses should use the Sign function in this package directly.
+ func (priv *PrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOpts) ([]byte, error) {
 +      if boring.Enabled && rand == boring.RandReader {
 +              b, err := boringPrivateKey(priv)
 +              if err != nil {
 +                      return nil, err
 +              }
-               return boring.SignMarshalECDSA(b, msg)
++              return boring.SignMarshalECDSA(b, digest)
 +      }
 +      boring.UnreachableExceptTests()
 +
-       r, s, err := Sign(rand, priv, msg)
+       r, s, err := Sign(rand, priv, digest)
        if err != nil {
                return nil, err
        }
index 69969636600e5092fb1f5da523d96fa369561404,3c8e727bc8c3d48122d71eeb8008f09bcd6b8b7a..4576b9843bd30994af3084752be2034f7df9be09
@@@ -65,14 -64,10 +65,17 @@@ func (h *hmac) Reset() 
  }
  
  // New returns a new HMAC hash using the given hash.Hash type and key.
+ // Note that unlike other hash implementations in the standard library,
+ // the returned Hash does not implement encoding.BinaryMarshaler
+ // or encoding.BinaryUnmarshaler.
  func New(h func() hash.Hash, key []byte) hash.Hash {
 +      if boring.Enabled {
 +              hm := boring.NewHMAC(h, key)
 +              if hm != nil {
 +                      return hm
 +              }
 +              // BoringCrypto did not recognize h, so fall through to standard Go code.
 +      }
        hm := new(hmac)
        hm.outer = h()
        hm.inner = h()
index 0000000000000000000000000000000000000000,b4276df4e1100d9b1d5a79622162b27a12fbdf67..466208879991e1a12ecf92d34b53d71885ed1b08
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,61 +1,61 @@@
 -package crypto
+ // Copyright 2017 The Go Authors. All rights reserved.
+ // Use of this source code is governed by a BSD-style
+ // license that can be found in the LICENSE file.
++package crypto_test
+ import (
+       "crypto/aes"
+       "crypto/cipher"
+       "crypto/rc4"
+       "testing"
+ )
+ func TestRC4OutOfBoundsWrite(t *testing.T) {
+       // This cipherText is encrypted "0123456789"
+       cipherText := []byte{238, 41, 187, 114, 151, 2, 107, 13, 178, 63}
+       cipher, err := rc4.NewCipher([]byte{0})
+       if err != nil {
+               panic(err)
+       }
+       test(t, "RC4", cipherText, cipher.XORKeyStream)
+ }
+ func TestCTROutOfBoundsWrite(t *testing.T) {
+       testBlock(t, "CTR", cipher.NewCTR)
+ }
+ func TestOFBOutOfBoundsWrite(t *testing.T) {
+       testBlock(t, "OFB", cipher.NewOFB)
+ }
+ func TestCFBEncryptOutOfBoundsWrite(t *testing.T) {
+       testBlock(t, "CFB Encrypt", cipher.NewCFBEncrypter)
+ }
+ func TestCFBDecryptOutOfBoundsWrite(t *testing.T) {
+       testBlock(t, "CFB Decrypt", cipher.NewCFBDecrypter)
+ }
+ func testBlock(t *testing.T, name string, newCipher func(cipher.Block, []byte) cipher.Stream) {
+       // This cipherText is encrypted "0123456789"
+       cipherText := []byte{86, 216, 121, 231, 219, 191, 26, 12, 176, 117}
+       var iv, key [16]byte
+       block, err := aes.NewCipher(key[:])
+       if err != nil {
+               panic(err)
+       }
+       stream := newCipher(block, iv[:])
+       test(t, name, cipherText, stream.XORKeyStream)
+ }
+ func test(t *testing.T, name string, cipherText []byte, xor func([]byte, []byte)) {
+       want := "abcdefghij"
+       plainText := []byte(want)
+       shorterLen := len(cipherText) / 2
+       defer func() {
+               err := recover()
+               if err == nil {
+                       t.Errorf("%v XORKeyStream expected to panic on len(dst) < len(src), but didn't", name)
+               }
+               const plain = "0123456789"
+               if plainText[shorterLen] == plain[shorterLen] {
+                       t.Errorf("%v XORKeyStream did out of bounds write, want %v, got %v", name, want, string(plainText))
+               }
+       }()
+       xor(plainText[:shorterLen], cipherText)
+ }
Simple merge
Simple merge
index 535937e902847fbf517780e71787557ad4542105,5f32434f0f94d46ba4dadf728df6d3300b165078..3badf558852b2d27fd241e202eb1ce2721a97cfa
@@@ -50,11 -113,10 +113,13 @@@ func (d *digest) Reset() 
        d.len = 0
  }
  
- // New returns a new hash.Hash computing the SHA1 checksum.
+ // New returns a new hash.Hash computing the SHA1 checksum. The Hash also
+ // implements encoding.BinaryMarshaler and encoding.BinaryUnmarshaler to
+ // marshal and unmarshal the internal state of the hash.
  func New() hash.Hash {
 +      if boringEnabled {
 +              return boringNewSHA1()
 +      }
        d := new(digest)
        d.Reset()
        return d
index 426402a8c25a049f52d872d1bfc16d264b701384,8fefde0db2dad470d82330837798dd2ac4762f2a..20095190c3efb1afb9db314d149a2315cadfd832
@@@ -7,8 -7,9 +7,10 @@@
  package sha1
  
  import (
+       "bytes"
 +      "crypto/internal/boring"
        "crypto/rand"
+       "encoding"
        "fmt"
        "io"
        "testing"
index f386f832067865052e6d55df7469de20e28461db,f078cab3783bcc6fcf9c918c746a6f57b5a6c79f..a5bb144f0e2f7b4e9d87ed73131474fe92dd415f
@@@ -8,7 -8,7 +8,8 @@@ package sha25
  
  import (
        "crypto"
 +      "crypto/internal/boring"
+       "errors"
        "hash"
  )
  
@@@ -79,11 -164,11 +165,14 @@@ func (d *digest) Reset() 
        d.len = 0
  }
  
- // New returns a new hash.Hash computing the SHA256 checksum.
+ // New returns a new hash.Hash computing the SHA256 checksum. The Hash
+ // also implements encoding.BinaryMarshaler and
+ // encoding.BinaryUnmarshaler to marshal and unmarshal the internal
+ // state of the hash.
  func New() hash.Hash {
 +      if boring.Enabled {
 +              return boring.NewSHA256()
 +      }
        d := new(digest)
        d.Reset()
        return d
index 17721d563519a2584cd0a7926f34165f755885a1,cd402864e52d367a9122be8c9879bcec22be2a08..a188a64ad18792df250e8ceb4c60b4f6b376c089
@@@ -7,9 -7,11 +7,12 @@@
  package sha256
  
  import (
+       "bytes"
 +      "crypto/internal/boring"
        "crypto/rand"
+       "encoding"
        "fmt"
+       "hash"
        "io"
        "testing"
  )
index d37f853499ffda8545278f53035980754085181a,2ea27c5535b225aac8e5af9f5b619bef2216c275..81918e4fcfd27a09735e9dd0e39d867aeafa9a4d
@@@ -8,7 -12,7 +12,8 @@@ package sha51
  
  import (
        "crypto"
 +      "crypto/internal/boring"
+       "errors"
        "hash"
  )
  
@@@ -125,11 -129,94 +130,97 @@@ func (d *digest) Reset() 
        d.len = 0
  }
  
+ const (
+       magic384      = "sha\x04"
+       magic512_224  = "sha\x05"
+       magic512_256  = "sha\x06"
+       magic512      = "sha\x07"
+       marshaledSize = len(magic512) + 8*8 + chunk + 8
+ )
+ func (d *digest) MarshalBinary() ([]byte, error) {
+       b := make([]byte, 0, marshaledSize)
+       switch d.function {
+       case crypto.SHA384:
+               b = append(b, magic384...)
+       case crypto.SHA512_224:
+               b = append(b, magic512_224...)
+       case crypto.SHA512_256:
+               b = append(b, magic512_256...)
+       case crypto.SHA512:
+               b = append(b, magic512...)
+       default:
+               return nil, errors.New("crypto/sha512: invalid hash function")
+       }
+       b = appendUint64(b, d.h[0])
+       b = appendUint64(b, d.h[1])
+       b = appendUint64(b, d.h[2])
+       b = appendUint64(b, d.h[3])
+       b = appendUint64(b, d.h[4])
+       b = appendUint64(b, d.h[5])
+       b = appendUint64(b, d.h[6])
+       b = appendUint64(b, d.h[7])
+       b = append(b, d.x[:]...)
+       b = appendUint64(b, d.len)
+       return b, nil
+ }
+ func (d *digest) UnmarshalBinary(b []byte) error {
+       if len(b) < len(magic512) {
+               return errors.New("crypto/sha512: invalid hash state identifier")
+       }
+       switch {
+       case d.function == crypto.SHA384 && string(b[:len(magic384)]) == magic384:
+       case d.function == crypto.SHA512_224 && string(b[:len(magic512_224)]) == magic512_224:
+       case d.function == crypto.SHA512_256 && string(b[:len(magic512_256)]) == magic512_256:
+       case d.function == crypto.SHA512 && string(b[:len(magic512)]) == magic512:
+       default:
+               return errors.New("crypto/sha512: invalid hash state identifier")
+       }
+       if len(b) != marshaledSize {
+               return errors.New("crypto/sha512: invalid hash state size")
+       }
+       b = b[len(magic512):]
+       b, d.h[0] = consumeUint64(b)
+       b, d.h[1] = consumeUint64(b)
+       b, d.h[2] = consumeUint64(b)
+       b, d.h[3] = consumeUint64(b)
+       b, d.h[4] = consumeUint64(b)
+       b, d.h[5] = consumeUint64(b)
+       b, d.h[6] = consumeUint64(b)
+       b, d.h[7] = consumeUint64(b)
+       b = b[copy(d.x[:], b):]
+       b, d.len = consumeUint64(b)
+       d.nx = int(d.len) % chunk
+       return nil
+ }
+ func appendUint64(b []byte, x uint64) []byte {
+       a := [8]byte{
+               byte(x >> 56),
+               byte(x >> 48),
+               byte(x >> 40),
+               byte(x >> 32),
+               byte(x >> 24),
+               byte(x >> 16),
+               byte(x >> 8),
+               byte(x),
+       }
+       return append(b, a[:]...)
+ }
+ func consumeUint64(b []byte) ([]byte, uint64) {
+       _ = b[7]
+       x := uint64(b[7]) | uint64(b[6])<<8 | uint64(b[5])<<16 | uint64(b[4])<<24 |
+               uint64(b[3])<<32 | uint64(b[2])<<40 | uint64(b[1])<<48 | uint64(b[0])<<56
+       return b[8:], x
+ }
  // New returns a new hash.Hash computing the SHA-512 checksum.
  func New() hash.Hash {
 +      if boring.Enabled {
 +              return boring.NewSHA512()
 +      }
        d := &digest{function: crypto.SHA512}
        d.Reset()
        return d
index 2c41d1a3ecedb280659220c88fc308af507e84da,4423cf5f18952d1389e0665c292cf882c3ee0fb3..93c4591bd87d53552327386d75af454eb1326f72
@@@ -7,8 -7,9 +7,10 @@@
  package sha512
  
  import (
+       "bytes"
 +      "crypto/internal/boring"
        "crypto/rand"
+       "encoding"
        "encoding/hex"
        "hash"
        "io"
index 791049f0d3ad0015ccb041e009d82ada186ea2ba,0000000000000000000000000000000000000000..f6d922c673f5e99b9bfc3cee8d71723544912116
mode 100644,000000..100644
--- /dev/null
@@@ -1,121 -1,0 +1,121 @@@
- func supportedSignatureAlgorithms() []signatureAndHash {
 +// Copyright 2017 The Go Authors. All rights reserved.
 +// Use of this source code is governed by a BSD-style
 +// license that can be found in the LICENSE file.
 +
 +package tls
 +
 +import (
 +      "crypto/ecdsa"
 +      "crypto/internal/boring/fipstls"
 +      "crypto/rsa"
 +      "crypto/x509"
 +)
 +
 +// needFIPS returns fipstls.Required(); it avoids a new import in common.go.
 +func needFIPS() bool {
 +      return fipstls.Required()
 +}
 +
 +// fipsMinVersion replaces c.minVersion in FIPS-only mode.
 +func fipsMinVersion(c *Config) uint16 {
 +      // FIPS requires TLS 1.2.
 +      return VersionTLS12
 +}
 +
 +// fipsMaxVersion replaces c.maxVersion in FIPS-only mode.
 +func fipsMaxVersion(c *Config) uint16 {
 +      // FIPS requires TLS 1.2.
 +      return VersionTLS12
 +}
 +
 +// default defaultFIPSCurvePreferences is the FIPS-allowed curves,
 +// in preference order (most preferable first).
 +var defaultFIPSCurvePreferences = []CurveID{CurveP256, CurveP384, CurveP521}
 +
 +// fipsCurvePreferences replaces c.curvePreferences in FIPS-only mode.
 +func fipsCurvePreferences(c *Config) []CurveID {
 +      if c == nil || len(c.CurvePreferences) == 0 {
 +              return defaultFIPSCurvePreferences
 +      }
 +      var list []CurveID
 +      for _, id := range c.CurvePreferences {
 +              for _, allowed := range defaultFIPSCurvePreferences {
 +                      if id == allowed {
 +                              list = append(list, id)
 +                              break
 +                      }
 +              }
 +      }
 +      return list
 +}
 +
 +// default FIPSCipherSuites is the FIPS-allowed cipher suites,
 +// in preference order (most preferable first).
 +var defaultFIPSCipherSuites = []uint16{
 +      TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
 +      TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
 +      TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
 +      TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
 +      TLS_RSA_WITH_AES_128_GCM_SHA256,
 +      TLS_RSA_WITH_AES_256_GCM_SHA384,
 +}
 +
 +// fipsCipherSuites replaces c.cipherSuites in FIPS-only mode.
 +func fipsCipherSuites(c *Config) []uint16 {
 +      if c == nil || c.CipherSuites == nil {
 +              return defaultFIPSCipherSuites
 +      }
 +      var list []uint16
 +      for _, id := range c.CipherSuites {
 +              for _, allowed := range defaultFIPSCipherSuites {
 +                      if id == allowed {
 +                              list = append(list, id)
 +                              break
 +                      }
 +              }
 +      }
 +      return list
 +}
 +
 +// isBoringCertificate reports whether a certificate may be used
 +// when constructing a verified chain.
 +// It is called for each leaf, intermediate, and root certificate.
 +func isBoringCertificate(c *x509.Certificate) bool {
 +      if !needFIPS() {
 +              // Everything is OK if we haven't forced FIPS-only mode.
 +              return true
 +      }
 +
 +      // Otherwise the key must be RSA 2048, RSA 3072, or ECDSA P-256.
 +      switch k := c.PublicKey.(type) {
 +      default:
 +              return false
 +      case *rsa.PublicKey:
 +              if size := k.N.BitLen(); size != 2048 && size != 3072 {
 +                      return false
 +              }
 +      case *ecdsa.PublicKey:
 +              if name := k.Curve.Params().Name; name != "P-256" && name != "P-384" {
 +                      return false
 +              }
 +      }
 +
 +      return true
 +}
 +
 +// supportedSignatureAlgorithms returns the supported signature algorithms.
 +// It knows that the FIPS-allowed ones are all at the beginning of
 +// defaultSupportedSignatureAlgorithms.
-       for i < len(all) && all[i].hash != hashSHA1 {
++func supportedSignatureAlgorithms() []SignatureScheme {
 +      all := defaultSupportedSignatureAlgorithms
 +      if !needFIPS() {
 +              return all
 +      }
 +      i := 0
- var testingOnlyForceClientHelloSignatureAndHashes []signatureAndHash
++      for i < len(all) && all[i] != PKCS1WithSHA1 {
 +              i++
 +      }
 +      return all[:i]
 +}
 +
++var testingOnlyForceClientHelloSignatureAlgorithms []SignatureScheme
index 15422f8adf1262c93223813eb9176da7fc557af2,0000000000000000000000000000000000000000..f31f3f6bc8c4a2e67398ae73400e5a4e08c680c5
mode 100644,000000..100644
--- /dev/null
@@@ -1,579 -1,0 +1,576 @@@
- func isBoringSignatureAndHash(sigHash signatureAndHash) bool {
-       switch sigHash.signature {
 +// Copyright 2017 The Go Authors. All rights reserved.
 +// Use of this source code is governed by a BSD-style
 +// license that can be found in the LICENSE file.
 +
 +package tls
 +
 +import (
 +      "crypto/ecdsa"
 +      "crypto/elliptic"
 +      "crypto/internal/boring/fipstls"
 +      "crypto/rand"
 +      "crypto/rsa"
 +      "crypto/x509"
 +      "crypto/x509/pkix"
 +      "fmt"
 +      "math/big"
 +      "net"
 +      "runtime"
 +      "strings"
 +      "testing"
 +      "time"
 +)
 +
 +func TestBoringServerProtocolVersion(t *testing.T) {
 +      test := func(name string, v uint16, msg string) {
 +              t.Run(name, func(t *testing.T) {
 +                      serverConfig := testConfig.Clone()
 +                      serverConfig.MinVersion = VersionSSL30
 +                      clientHello := &clientHelloMsg{
 +                              vers:               v,
 +                              cipherSuites:       allCipherSuites(),
 +                              compressionMethods: []uint8{compressionNone},
 +                      }
 +                      testClientHelloFailure(t, serverConfig, clientHello, msg)
 +              })
 +      }
 +
 +      test("VersionSSL30", VersionSSL30, "")
 +      test("VersionTLS10", VersionTLS10, "")
 +      test("VersionTLS11", VersionTLS11, "")
 +      test("VersionTLS12", VersionTLS12, "")
 +
 +      fipstls.Force()
 +      defer fipstls.Abandon()
 +      test("VersionSSL30", VersionSSL30, "unsupported, maximum protocol version")
 +      test("VersionTLS10", VersionTLS10, "unsupported, maximum protocol version")
 +      test("VersionTLS11", VersionTLS11, "unsupported, maximum protocol version")
 +      test("VersionTLS12", VersionTLS12, "")
 +}
 +
 +func isBoringCipherSuite(id uint16) bool {
 +      switch id {
 +      case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
 +              TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
 +              TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
 +              TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
 +              TLS_RSA_WITH_AES_128_GCM_SHA256,
 +              TLS_RSA_WITH_AES_256_GCM_SHA384:
 +              return true
 +      }
 +      return false
 +}
 +
 +func isBoringCurve(id CurveID) bool {
 +      switch id {
 +      case CurveP256, CurveP384, CurveP521:
 +              return true
 +      }
 +      return false
 +}
 +
 +func isECDSA(id uint16) bool {
 +      for _, suite := range cipherSuites {
 +              if suite.id == id {
 +                      return suite.flags&suiteECDSA == suiteECDSA
 +              }
 +      }
 +      panic(fmt.Sprintf("unknown cipher suite %#x", id))
 +}
 +
-       case signatureRSA,
-               signatureECDSA:
-               // ok
-       }
-       switch sigHash.hash {
-       default:
-               return false
-       case hashSHA256,
-               hashSHA384:
++func isBoringSignatureScheme(alg SignatureScheme) bool {
++      switch alg {
 +      default:
 +              return false
-               testingOnlyForceClientHelloSignatureAndHashes = nil
++      case PKCS1WithSHA256,
++              ECDSAWithP256AndSHA256,
++              PKCS1WithSHA384,
++              ECDSAWithP384AndSHA384,
++              PKCS1WithSHA512,
++              ECDSAWithP521AndSHA512:
 +              // ok
 +      }
 +      return true
 +}
 +
 +func TestBoringServerCipherSuites(t *testing.T) {
 +      serverConfig := testConfig.Clone()
 +      serverConfig.CipherSuites = allCipherSuites()
 +      serverConfig.Certificates = make([]Certificate, 1)
 +
 +      for _, id := range allCipherSuites() {
 +              if isECDSA(id) {
 +                      serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate}
 +                      serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey
 +              } else {
 +                      serverConfig.Certificates[0].Certificate = [][]byte{testRSACertificate}
 +                      serverConfig.Certificates[0].PrivateKey = testRSAPrivateKey
 +              }
 +              serverConfig.BuildNameToCertificate()
 +              t.Run(fmt.Sprintf("suite=%#x", id), func(t *testing.T) {
 +                      clientHello := &clientHelloMsg{
 +                              vers:               VersionTLS12,
 +                              cipherSuites:       []uint16{id},
 +                              compressionMethods: []uint8{compressionNone},
 +                              supportedCurves:    defaultCurvePreferences,
 +                              supportedPoints:    []uint8{pointFormatUncompressed},
 +                      }
 +
 +                      testClientHello(t, serverConfig, clientHello)
 +                      t.Run("fipstls", func(t *testing.T) {
 +                              fipstls.Force()
 +                              defer fipstls.Abandon()
 +                              msg := ""
 +                              if !isBoringCipherSuite(id) {
 +                                      msg = "no cipher suite supported by both client and server"
 +                              }
 +                              testClientHelloFailure(t, serverConfig, clientHello, msg)
 +                      })
 +              })
 +      }
 +}
 +
 +func TestBoringServerCurves(t *testing.T) {
 +      serverConfig := testConfig.Clone()
 +      serverConfig.Certificates = make([]Certificate, 1)
 +      serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate}
 +      serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey
 +      serverConfig.BuildNameToCertificate()
 +
 +      for _, curveid := range defaultCurvePreferences {
 +              t.Run(fmt.Sprintf("curve=%d", curveid), func(t *testing.T) {
 +                      clientHello := &clientHelloMsg{
 +                              vers:               VersionTLS12,
 +                              cipherSuites:       []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
 +                              compressionMethods: []uint8{compressionNone},
 +                              supportedCurves:    []CurveID{curveid},
 +                              supportedPoints:    []uint8{pointFormatUncompressed},
 +                      }
 +
 +                      testClientHello(t, serverConfig, clientHello)
 +
 +                      // With fipstls forced, bad curves should be rejected.
 +                      t.Run("fipstls", func(t *testing.T) {
 +                              fipstls.Force()
 +                              defer fipstls.Abandon()
 +                              msg := ""
 +                              if !isBoringCurve(curveid) {
 +                                      msg = "no cipher suite supported by both client and server"
 +                              }
 +                              testClientHelloFailure(t, serverConfig, clientHello, msg)
 +                      })
 +              })
 +      }
 +}
 +
 +func boringHandshake(t *testing.T, clientConfig, serverConfig *Config) (clientErr, serverErr error) {
 +      c, s := realNetPipe(t)
 +      client := Client(c, clientConfig)
 +      server := Server(s, serverConfig)
 +      done := make(chan error, 1)
 +      go func() {
 +              done <- client.Handshake()
 +              c.Close()
 +      }()
 +      serverErr = server.Handshake()
 +      s.Close()
 +      clientErr = <-done
 +      return
 +}
 +
 +func TestBoringServerSignatureAndHash(t *testing.T) {
 +      serverConfig := testConfig.Clone()
 +      serverConfig.Certificates = make([]Certificate, 1)
 +
 +      defer func() {
-               testingOnlyForceClientHelloSignatureAndHashes = []signatureAndHash{sigHash}
++              testingOnlyForceClientHelloSignatureAlgorithms = nil
 +      }()
 +
 +      for _, sigHash := range defaultSupportedSignatureAlgorithms {
-                       if sigHash.signature == signatureRSA {
++              testingOnlyForceClientHelloSignatureAlgorithms = []SignatureScheme{sigHash}
 +
 +              t.Run(fmt.Sprintf("%v", sigHash), func(t *testing.T) {
-                               if isBoringSignatureAndHash(sigHash) {
++                      if sigHash == PKCS1WithSHA1 || sigHash == PKCS1WithSHA256 || sigHash == PKCS1WithSHA384 || sigHash == PKCS1WithSHA512 {
 +                              serverConfig.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}
 +                              serverConfig.Certificates[0].Certificate = [][]byte{testRSACertificate}
 +                              serverConfig.Certificates[0].PrivateKey = testRSAPrivateKey
 +                      } else {
 +                              serverConfig.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}
 +                              serverConfig.Certificates = make([]Certificate, 1)
 +                              serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate}
 +                              serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey
 +                      }
 +                      serverConfig.BuildNameToCertificate()
 +
 +                      clientErr, _ := boringHandshake(t, testConfig, serverConfig)
 +                      if clientErr != nil {
 +                              t.Fatalf("expected handshake with %v to succeed; err=%v", sigHash, clientErr)
 +                      }
 +
 +                      // With fipstls forced, bad curves should be rejected.
 +                      t.Run("fipstls", func(t *testing.T) {
 +                              fipstls.Force()
 +                              defer fipstls.Abandon()
 +                              clientErr, _ := boringHandshake(t, testConfig, serverConfig)
-       for _, sigHash := range hello.signatureAndHashes {
-               if !isBoringSignatureAndHash(sigHash) {
++                              if isBoringSignatureScheme(sigHash) {
 +                                      if clientErr != nil {
 +                                              t.Fatalf("expected handshake with %v to succeed; err=%v", sigHash, clientErr)
 +                                      }
 +                              } else {
 +                                      if clientErr == nil {
 +                                              t.Fatalf("expected handshake with %v to fail, but it succeeded", sigHash)
 +                                      }
 +                              }
 +                      })
 +              })
 +      }
 +}
 +
 +func TestBoringClientHello(t *testing.T) {
 +      // Test that no matter what we put in the client config,
 +      // the client does not offer non-FIPS configurations.
 +      fipstls.Force()
 +      defer fipstls.Abandon()
 +
 +      c, s := net.Pipe()
 +      defer c.Close()
 +      defer s.Close()
 +
 +      clientConfig := testConfig.Clone()
 +      // All sorts of traps for the client to avoid.
 +      clientConfig.MinVersion = VersionSSL30
 +      clientConfig.CipherSuites = allCipherSuites()
 +      clientConfig.CurvePreferences = defaultCurvePreferences
 +
 +      go Client(c, testConfig).Handshake()
 +      srv := Server(s, testConfig)
 +      msg, err := srv.readHandshake()
 +      if err != nil {
 +              t.Fatal(err)
 +      }
 +      hello, ok := msg.(*clientHelloMsg)
 +      if !ok {
 +              t.Fatalf("unexpected message type %T", msg)
 +      }
 +
 +      if hello.vers != VersionTLS12 {
 +              t.Errorf("client vers=%#x, want %#x (TLS 1.2)", hello.vers, VersionTLS12)
 +      }
 +      for _, id := range hello.cipherSuites {
 +              if !isBoringCipherSuite(id) {
 +                      t.Errorf("client offered disallowed suite %#x", id)
 +              }
 +      }
 +      for _, id := range hello.supportedCurves {
 +              if !isBoringCurve(id) {
 +                      t.Errorf("client offered disallowed curve %d", id)
 +              }
 +      }
++      for _, sigHash := range hello.supportedSignatureAlgorithms {
++              if !isBoringSignatureScheme(sigHash) {
 +                      t.Errorf("client offered disallowed signature-and-hash %v", sigHash)
 +              }
 +      }
 +}
 +
 +func TestBoringCertAlgs(t *testing.T) {
 +      // NaCl and arm time out generating keys. Nothing in this test is architecture-specific, so just don't bother on those.
 +      if runtime.GOOS == "nacl" || runtime.GOARCH == "arm" {
 +              t.Skipf("skipping on %s/%s because key generation takes too long", runtime.GOOS, runtime.GOARCH)
 +      }
 +
 +      // Set up some roots, intermediate CAs, and leaf certs with various algorithms.
 +      // X_Y is X signed by Y.
 +      R1 := boringCert(t, "R1", boringRSAKey(t, 2048), nil, boringCertCA|boringCertFIPSOK)
 +      R2 := boringCert(t, "R2", boringRSAKey(t, 4096), nil, boringCertCA)
 +
 +      M1_R1 := boringCert(t, "M1_R1", boringECDSAKey(t, elliptic.P256()), R1, boringCertCA|boringCertFIPSOK)
 +      M2_R1 := boringCert(t, "M2_R1", boringECDSAKey(t, elliptic.P224()), R1, boringCertCA)
 +
 +      I_R1 := boringCert(t, "I_R1", boringRSAKey(t, 3072), R1, boringCertCA|boringCertFIPSOK)
 +      I_R2 := boringCert(t, "I_R2", I_R1.key, R2, boringCertCA|boringCertFIPSOK)
 +      I_M1 := boringCert(t, "I_M1", I_R1.key, M1_R1, boringCertCA|boringCertFIPSOK)
 +      I_M2 := boringCert(t, "I_M2", I_R1.key, M2_R1, boringCertCA|boringCertFIPSOK)
 +
 +      L1_I := boringCert(t, "L1_I", boringECDSAKey(t, elliptic.P384()), I_R1, boringCertLeaf|boringCertFIPSOK)
 +      L2_I := boringCert(t, "L2_I", boringRSAKey(t, 1024), I_R1, boringCertLeaf)
 +
 +      // boringCert checked that isBoringCertificate matches the caller's boringCertFIPSOK bit.
 +      // If not, no point in building bigger end-to-end tests.
 +      if t.Failed() {
 +              t.Fatalf("isBoringCertificate failures; not continuing")
 +      }
 +
 +      // client verifying server cert
 +      testServerCert := func(t *testing.T, desc string, pool *x509.CertPool, key interface{}, list [][]byte, ok bool) {
 +              clientConfig := testConfig.Clone()
 +              clientConfig.RootCAs = pool
 +              clientConfig.InsecureSkipVerify = false
 +              clientConfig.ServerName = "example.com"
 +
 +              serverConfig := testConfig.Clone()
 +              serverConfig.Certificates = []Certificate{{Certificate: list, PrivateKey: key}}
 +              serverConfig.BuildNameToCertificate()
 +
 +              clientErr, _ := boringHandshake(t, clientConfig, serverConfig)
 +
 +              if (clientErr == nil) == ok {
 +                      if ok {
 +                              t.Logf("%s: accept", desc)
 +                      } else {
 +                              t.Logf("%s: reject", desc)
 +                      }
 +              } else {
 +                      if ok {
 +                              t.Errorf("%s: BAD reject (%v)", desc, clientErr)
 +                      } else {
 +                              t.Errorf("%s: BAD accept", desc)
 +                      }
 +              }
 +      }
 +
 +      // server verifying client cert
 +      testClientCert := func(t *testing.T, desc string, pool *x509.CertPool, key interface{}, list [][]byte, ok bool) {
 +              clientConfig := testConfig.Clone()
 +              clientConfig.ServerName = "example.com"
 +              clientConfig.Certificates = []Certificate{{Certificate: list, PrivateKey: key}}
 +
 +              serverConfig := testConfig.Clone()
 +              serverConfig.ClientCAs = pool
 +              serverConfig.ClientAuth = RequireAndVerifyClientCert
 +
 +              _, serverErr := boringHandshake(t, clientConfig, serverConfig)
 +
 +              if (serverErr == nil) == ok {
 +                      if ok {
 +                              t.Logf("%s: accept", desc)
 +                      } else {
 +                              t.Logf("%s: reject", desc)
 +                      }
 +              } else {
 +                      if ok {
 +                              t.Errorf("%s: BAD reject (%v)", desc, serverErr)
 +                      } else {
 +                              t.Errorf("%s: BAD accept", desc)
 +                      }
 +              }
 +      }
 +
 +      // Run simple basic test with known answers before proceeding to
 +      // exhaustive test with computed answers.
 +      r1pool := x509.NewCertPool()
 +      r1pool.AddCert(R1.cert)
 +      testServerCert(t, "basic", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, true)
 +      testClientCert(t, "basic (client cert)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, true)
 +      fipstls.Force()
 +      testServerCert(t, "basic (fips)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, false)
 +      testClientCert(t, "basic (fips, client cert)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, false)
 +      fipstls.Abandon()
 +
 +      if t.Failed() {
 +              t.Fatal("basic test failed, skipping exhaustive test")
 +      }
 +
 +      if testing.Short() {
 +              t.Logf("basic test passed; skipping exhaustive test in -short mode")
 +              return
 +      }
 +
 +      for l := 1; l <= 2; l++ {
 +              leaf := L1_I
 +              if l == 2 {
 +                      leaf = L2_I
 +              }
 +              for i := 0; i < 64; i++ {
 +                      reachable := map[string]bool{leaf.parentOrg: true}
 +                      reachableFIPS := map[string]bool{leaf.parentOrg: leaf.fipsOK}
 +                      list := [][]byte{leaf.der}
 +                      listName := leaf.name
 +                      addList := func(cond int, c *boringCertificate) {
 +                              if cond != 0 {
 +                                      list = append(list, c.der)
 +                                      listName += "," + c.name
 +                                      if reachable[c.org] {
 +                                              reachable[c.parentOrg] = true
 +                                      }
 +                                      if reachableFIPS[c.org] && c.fipsOK {
 +                                              reachableFIPS[c.parentOrg] = true
 +                                      }
 +                              }
 +                      }
 +                      addList(i&1, I_R1)
 +                      addList(i&2, I_R2)
 +                      addList(i&4, I_M1)
 +                      addList(i&8, I_M2)
 +                      addList(i&16, M1_R1)
 +                      addList(i&32, M2_R1)
 +
 +                      for r := 1; r <= 3; r++ {
 +                              pool := x509.NewCertPool()
 +                              rootName := ","
 +                              shouldVerify := false
 +                              shouldVerifyFIPS := false
 +                              addRoot := func(cond int, c *boringCertificate) {
 +                                      if cond != 0 {
 +                                              rootName += "," + c.name
 +                                              pool.AddCert(c.cert)
 +                                              if reachable[c.org] {
 +                                                      shouldVerify = true
 +                                              }
 +                                              if reachableFIPS[c.org] && c.fipsOK {
 +                                                      shouldVerifyFIPS = true
 +                                              }
 +                                      }
 +                              }
 +                              addRoot(r&1, R1)
 +                              addRoot(r&2, R2)
 +                              rootName = rootName[1:] // strip leading comma
 +                              testServerCert(t, listName+"->"+rootName[1:], pool, leaf.key, list, shouldVerify)
 +                              testClientCert(t, listName+"->"+rootName[1:]+"(client cert)", pool, leaf.key, list, shouldVerify)
 +                              fipstls.Force()
 +                              testServerCert(t, listName+"->"+rootName[1:]+" (fips)", pool, leaf.key, list, shouldVerifyFIPS)
 +                              testClientCert(t, listName+"->"+rootName[1:]+" (fips, client cert)", pool, leaf.key, list, shouldVerifyFIPS)
 +                              fipstls.Abandon()
 +                      }
 +              }
 +      }
 +}
 +
 +const (
 +      boringCertCA = iota
 +      boringCertLeaf
 +      boringCertFIPSOK = 0x80
 +)
 +
 +func boringRSAKey(t *testing.T, size int) *rsa.PrivateKey {
 +      k, err := rsa.GenerateKey(rand.Reader, size)
 +      if err != nil {
 +              t.Fatal(err)
 +      }
 +      return k
 +}
 +
 +func boringECDSAKey(t *testing.T, curve elliptic.Curve) *ecdsa.PrivateKey {
 +      k, err := ecdsa.GenerateKey(curve, rand.Reader)
 +      if err != nil {
 +              t.Fatal(err)
 +      }
 +      return k
 +}
 +
 +type boringCertificate struct {
 +      name      string
 +      org       string
 +      parentOrg string
 +      der       []byte
 +      cert      *x509.Certificate
 +      key       interface{}
 +      fipsOK    bool
 +}
 +
 +func boringCert(t *testing.T, name string, key interface{}, parent *boringCertificate, mode int) *boringCertificate {
 +      org := name
 +      parentOrg := ""
 +      if i := strings.Index(org, "_"); i >= 0 {
 +              org = org[:i]
 +              parentOrg = name[i+1:]
 +      }
 +      tmpl := &x509.Certificate{
 +              SerialNumber: big.NewInt(1),
 +              Subject: pkix.Name{
 +                      Organization: []string{org},
 +              },
 +              NotBefore: time.Unix(0, 0),
 +              NotAfter:  time.Unix(0, 0),
 +
 +              KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
 +              ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
 +              BasicConstraintsValid: true,
 +      }
 +      if mode&^boringCertFIPSOK == boringCertLeaf {
 +              tmpl.DNSNames = []string{"example.com"}
 +      } else {
 +              tmpl.IsCA = true
 +              tmpl.KeyUsage |= x509.KeyUsageCertSign
 +      }
 +
 +      var pcert *x509.Certificate
 +      var pkey interface{}
 +      if parent != nil {
 +              pcert = parent.cert
 +              pkey = parent.key
 +      } else {
 +              pcert = tmpl
 +              pkey = key
 +      }
 +
 +      var pub interface{}
 +      var desc string
 +      switch k := key.(type) {
 +      case *rsa.PrivateKey:
 +              pub = &k.PublicKey
 +              desc = fmt.Sprintf("RSA-%d", k.N.BitLen())
 +      case *ecdsa.PrivateKey:
 +              pub = &k.PublicKey
 +              desc = "ECDSA-" + k.Curve.Params().Name
 +      default:
 +              t.Fatalf("invalid key %T", key)
 +      }
 +
 +      der, err := x509.CreateCertificate(rand.Reader, tmpl, pcert, pub, pkey)
 +      if err != nil {
 +              t.Fatal(err)
 +      }
 +      cert, err := x509.ParseCertificate(der)
 +      if err != nil {
 +              t.Fatal(err)
 +      }
 +
 +      // Tell isBoringCertificate to enforce FIPS restrictions for this check.
 +      fipstls.Force()
 +      defer fipstls.Abandon()
 +
 +      fipsOK := mode&boringCertFIPSOK != 0
 +      if isBoringCertificate(cert) != fipsOK {
 +              t.Errorf("isBoringCertificate(cert with %s key) = %v, want %v", desc, !fipsOK, fipsOK)
 +      }
 +      return &boringCertificate{name, org, parentOrg, der, cert, key, fipsOK}
 +}
 +
 +func boringPool(t *testing.T, list ...*boringCertificate) *x509.CertPool {
 +      pool := x509.NewCertPool()
 +      for _, c := range list {
 +              cert, err := x509.ParseCertificate(c.der)
 +              if err != nil {
 +                      t.Fatal(err)
 +              }
 +              pool.AddCert(cert)
 +      }
 +      return pool
 +}
 +
 +func boringList(t *testing.T, list ...*boringCertificate) [][]byte {
 +      var all [][]byte
 +      for _, c := range list {
 +              all = append(all, c.der)
 +      }
 +      return all
 +}
 +
 +// realNetPipe is like net.Pipe but returns an actual network socket pair,
 +// which has buffering that avoids various deadlocks if both sides
 +// try to speak at the same time.
 +func realNetPipe(t *testing.T) (net.Conn, net.Conn) {
 +      l := newLocalListener(t)
 +      defer l.Close()
 +      c, err := net.Dial("tcp", l.Addr().String())
 +      if err != nil {
 +              t.Fatal(err)
 +      }
 +      s, err := l.Accept()
 +      if err != nil {
 +              c.Close()
 +              t.Fatal(err)
 +      }
 +      return c, s
 +}
index bf1128dd4e9a3d94ebc0bb136c94bb3f3b40969a,d4b0286b85392946c8641c18cf355a94b14545e3..a4641db7a66f1a634853437b7156d1bab1fa7d90
@@@ -139,22 -133,19 +133,19 @@@ const 
        signatureECDSA uint8 = 3
  )
  
- // signatureAndHash mirrors the TLS 1.2, SignatureAndHashAlgorithm struct. See
- // RFC 5246, section A.4.1.
- type signatureAndHash struct {
-       hash, signature uint8
- }
 -// supportedSignatureAlgorithms contains the signature and hash algorithms that
 +// defaultSupportedSignatureAlgorithms contains the signature and hash algorithms that
  // the code advertises as supported in a TLS 1.2 ClientHello and in a TLS 1.2
- // CertificateRequest.
- var defaultSupportedSignatureAlgorithms = []signatureAndHash{
-       {hashSHA256, signatureRSA},
-       {hashSHA256, signatureECDSA},
-       {hashSHA384, signatureRSA},
-       {hashSHA384, signatureECDSA},
-       {hashSHA1, signatureRSA},
-       {hashSHA1, signatureECDSA},
+ // CertificateRequest. The two fields are merged to match with TLS 1.3.
+ // Note that in TLS 1.2, the ECDSA algorithms are not constrained to P-256, etc.
 -var supportedSignatureAlgorithms = []SignatureScheme{
++var defaultSupportedSignatureAlgorithms = []SignatureScheme{
+       PKCS1WithSHA256,
+       ECDSAWithP256AndSHA256,
+       PKCS1WithSHA384,
+       ECDSAWithP384AndSHA384,
+       PKCS1WithSHA512,
+       ECDSAWithP521AndSHA512,
+       PKCS1WithSHA1,
+       ECDSAWithSHA1,
  }
  
  // ConnectionState records basic TLS details about the connection.
index 47a06bde49d5347f85b813af71d35bb3c62d576c,dc529c96d65d4427d076cae2327735beac470a57..8ab34c02e5346cd573ddead13b51ef9912658486
@@@ -99,11 -85,29 +85,32 @@@ NextCipherSuite
        }
  
        if hello.vers >= VersionTLS12 {
-               hello.signatureAndHashes = supportedSignatureAlgorithms()
 -              hello.supportedSignatureAlgorithms = supportedSignatureAlgorithms
++              hello.supportedSignatureAlgorithms = supportedSignatureAlgorithms()
++      }
++      if testingOnlyForceClientHelloSignatureAlgorithms != nil {
++              hello.supportedSignatureAlgorithms = testingOnlyForceClientHelloSignatureAlgorithms
        }
  
-       if testingOnlyForceClientHelloSignatureAndHashes != nil {
-               hello.signatureAndHashes = testingOnlyForceClientHelloSignatureAndHashes
+       return hello, nil
+ }
+ // c.out.Mutex <= L; c.handshakeMutex <= L.
+ func (c *Conn) clientHandshake() error {
+       if c.config == nil {
+               c.config = defaultConfig()
+       }
+       // This may be a renegotiation handshake, in which case some fields
+       // need to be reset.
+       c.didResume = false
+       hello, err := makeClientHello(c.config)
+       if err != nil {
+               return err
+       }
+       if c.handshakes > 0 {
+               hello.secureRenegotiation = c.clientFinished[:]
        }
  
        var session *ClientSessionState
index 7f3d03a4634fe3760c354b60a95e2b7126c0cf57,37eb748eea7b40684a9eb22fae05ba7d0706d622..1bf12c9ff245be16936c74cc4e528b3f7a089db9
@@@ -141,7 -145,7 +145,7 @@@ func (*clientHelloMsg) Generate(rand *r
                }
        }
        if rand.Intn(10) > 5 {
-               m.signatureAndHashes = supportedSignatureAlgorithms()
 -              m.supportedSignatureAlgorithms = supportedSignatureAlgorithms
++              m.supportedSignatureAlgorithms = supportedSignatureAlgorithms()
        }
        m.alpnProtocols = make([]string, rand.Intn(5))
        for i := range m.alpnProtocols {
index 93e664079f4bb8d7a68c4c581d06b8e535edf835,991b4e9e621e98fdc7aa254d0c7d7c3f4781d819..07e388a35ebf977eaff5df7a95f5595d2254aac5
@@@ -418,7 -418,7 +418,7 @@@ func (hs *serverHandshakeState) doFullH
                }
                if c.vers >= VersionTLS12 {
                        certReq.hasSignatureAndHash = true
-                       certReq.signatureAndHashes = supportedSignatureAlgorithms()
 -                      certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms
++                      certReq.supportedSignatureAlgorithms = supportedSignatureAlgorithms()
                }
  
                // An empty list of certificateAuthorities signals to
                }
  
                // Determine the signature type.
-               var signatureAndHash signatureAndHash
+               var signatureAlgorithm SignatureScheme
+               var sigType uint8
                if certVerify.hasSignatureAndHash {
-                       signatureAndHash = certVerify.signatureAndHash
-                       if !isSupportedSignatureAndHash(signatureAndHash, supportedSignatureAlgorithms()) {
+                       signatureAlgorithm = certVerify.signatureAlgorithm
 -                      if !isSupportedSignatureAlgorithm(signatureAlgorithm, supportedSignatureAlgorithms) {
++                      if !isSupportedSignatureAlgorithm(signatureAlgorithm, supportedSignatureAlgorithms()) {
                                return errors.New("tls: unsupported hash function for client certificate")
                        }
+                       sigType = signatureFromSignatureScheme(signatureAlgorithm)
                } else {
                        // Before TLS 1.2 the signature algorithm was implicit
                        // from the key type, and only one hash per signature
index e8a46b87084454ab9ae8559cacd7126f09ee63eb,3f570b66c69275d45b84900c7930bd1d1f092618..a168c5b260623cfdd079cd7cfff67b020861658e
@@@ -110,14 -110,14 +110,14 @@@ func md5SHA1Hash(slices [][]byte) []byt
  }
  
  // hashForServerKeyExchange hashes the given slices and returns their digest
- // and the identifier of the hash function used. The sigAndHash argument is
- // only used for >= TLS 1.2 and precisely identifies the hash function to use.
- func hashForServerKeyExchange(sigAndHash signatureAndHash, version uint16, slices ...[]byte) ([]byte, crypto.Hash, error) {
+ // and the identifier of the hash function used. The signatureAlgorithm argument
+ // is only used for >= TLS 1.2 and identifies the hash function to use.
+ func hashForServerKeyExchange(sigType uint8, signatureAlgorithm SignatureScheme, version uint16, slices ...[]byte) ([]byte, crypto.Hash, error) {
        if version >= VersionTLS12 {
-               if !isSupportedSignatureAndHash(sigAndHash, supportedSignatureAlgorithms()) {
 -              if !isSupportedSignatureAlgorithm(signatureAlgorithm, supportedSignatureAlgorithms) {
++              if !isSupportedSignatureAlgorithm(signatureAlgorithm, supportedSignatureAlgorithms()) {
                        return nil, crypto.Hash(0), errors.New("tls: unsupported hash function used by peer")
                }
-               hashFunc, err := lookupTLSHash(sigAndHash.hash)
+               hashFunc, err := lookupTLSHash(signatureAlgorithm)
                if err != nil {
                        return nil, crypto.Hash(0), err
                }
@@@ -142,15 -142,22 +142,22 @@@ func pickTLS12HashForSignature(sigType 
                // If the client didn't specify any signature_algorithms
                // extension then we can assume that it supports SHA1. See
                // http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
-               return hashSHA1, nil
+               switch sigType {
+               case signatureRSA:
+                       return PKCS1WithSHA1, nil
+               case signatureECDSA:
+                       return ECDSAWithSHA1, nil
+               default:
+                       return 0, errors.New("tls: unknown signature algorithm")
+               }
        }
  
-       for _, sigAndHash := range clientList {
-               if sigAndHash.signature != sigType {
+       for _, sigAlg := range clientList {
+               if signatureFromSignatureScheme(sigAlg) != sigType {
                        continue
                }
-               if isSupportedSignatureAndHash(sigAndHash, supportedSignatureAlgorithms()) {
-                       return sigAndHash.hash, nil
 -              if isSupportedSignatureAlgorithm(sigAlg, supportedSignatureAlgorithms) {
++              if isSupportedSignatureAlgorithm(sigAlg, supportedSignatureAlgorithms()) {
+                       return sigAlg, nil
                }
        }
  
index b93ce4fd2083034c8c281cc0fe1766050b09e7d1,74438f8bc84b59f6f9fa181c5c46576cba986151..7e64535a103b08c65d26770844b55398bde7117c
@@@ -310,16 -309,11 +309,11 @@@ func (h finishedHash) serverSum(masterS
        return out
  }
  
- // selectClientCertSignatureAlgorithm returns a signatureAndHash to sign a
+ // selectClientCertSignatureAlgorithm returns a SignatureScheme to sign a
  // client's CertificateVerify with, or an error if none can be found.
- func (h finishedHash) selectClientCertSignatureAlgorithm(serverList []signatureAndHash, sigType uint8) (signatureAndHash, error) {
-       if h.version < VersionTLS12 {
-               // Nothing to negotiate before TLS 1.2.
-               return signatureAndHash{signature: sigType}, nil
-       }
+ func (h finishedHash) selectClientCertSignatureAlgorithm(serverList []SignatureScheme, sigType uint8) (SignatureScheme, error) {
        for _, v := range serverList {
-               if v.signature == sigType && isSupportedSignatureAndHash(v, supportedSignatureAlgorithms()) {
 -              if signatureFromSignatureScheme(v) == sigType && isSupportedSignatureAlgorithm(v, supportedSignatureAlgorithms) {
++              if signatureFromSignatureScheme(v) == sigType && isSupportedSignatureAlgorithm(v, supportedSignatureAlgorithms()) {
                        return v, nil
                }
        }
index 999cb08cf3bc315e5d5b98a5f700aea5c3a80ca8,7a6bd454f201d5fc818469555188203b4599b6f9..d27ee3e249f15976ae815bc9ae8105fbc4cee435
@@@ -147,6 -174,6 +174,11 @@@ var errNotParsed = errors.New("x509: mi
  // VerifyOptions contains parameters for Certificate.Verify. It's a structure
  // because other PKIX verification APIs have ended up needing many options.
  type VerifyOptions struct {
++      // IsBoring is a validity check for BoringCrypto.
++      // If not nil, it will be called to check whether a given certificate
++      // can be used for constructing verification chains.
++      IsBoring func(*Certificate) bool
++
        DNSName       string
        Intermediates *CertPool
        Roots         *CertPool // if nil, the system roots are used
@@@ -263,13 -770,6 +775,13 @@@ func (c *Certificate) isValid(certType 
                }
        }
  
-               return CertificateInvalidError{c, IncompatibleUsage}
 +      if opts.IsBoring != nil && !opts.IsBoring(c) {
 +              // IncompatibleUsage is not quite right here,
 +              // but it's also the "no chains found" error
 +              // and is close enough.
++              return CertificateInvalidError{c, IncompatibleUsage, ""}
 +      }
 +
        return nil
  }
  
Simple merge
Simple merge
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..5a98b20253181cbc05c317f7eeb3c8cffdce9c2f
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,19 @@@
++// Copyright 2017 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package runtime
++
++import _ "unsafe" // for go:linkname
++
++//go:linkname boring_runtime_arg0 crypto/internal/boring.runtime_arg0
++func boring_runtime_arg0() string {
++      // On Windows, argslice is not set, and it's too much work to find argv0.
++      if len(argslice) == 0 {
++              return ""
++      }
++      return argslice[0]
++}
++
++//go:linkname fipstls_runtime_arg0 crypto/internal/boring/fipstls.runtime_arg0
++func fipstls_runtime_arg0() string { return boring_runtime_arg0() }