]> Cypherpunks.ru repositories - gostls13.git/commitdiff
[dev.boringcrypto] all: merge master into dev.boringcrypto
authorFilippo Valsorda <filippo@golang.org>
Fri, 29 Jun 2018 17:16:42 +0000 (13:16 -0400)
committerFilippo Valsorda <filippo@golang.org>
Tue, 3 Jul 2018 19:17:00 +0000 (15:17 -0400)
Add a couple of skips for slow js/wasm tests.

Change-Id: Ic95256b1d3c6e5e2f0cc536fad51e914d31cda9e

13 files changed:
1  2 
src/cmd/go/go_test.go
src/cmd/go/internal/load/pkg.go
src/cmd/link/internal/ld/lib.go
src/crypto/aes/cipher.go
src/crypto/aes/cipher_amd64.go
src/crypto/rsa/boring_test.go
src/crypto/tls/boring_test.go
src/crypto/tls/cipher_suites.go
src/crypto/tls/common.go
src/crypto/tls/handshake_client.go
src/crypto/tls/handshake_server.go
src/crypto/tls/key_agreement.go
src/go/build/deps_test.go

Simple merge
Simple merge
Simple merge
index fbd01a8f408241a55d9361fea81599297e30bd0d,bb93fbb36e289abfff7bf9b6341acf7769e719d3..db0ee38b78cea57e44cff31868025a58cfcff7e3
@@@ -6,7 -6,7 +6,8 @@@ package ae
  
  import (
        "crypto/cipher"
 +      "crypto/internal/boring"
+       "crypto/internal/subtle"
        "strconv"
  )
  
index 7efab31065d2fafb7faf9febc2bfd78e94c74fef,b12d9b46a2b7604ea4b126f6e91d40250bfc7eec..fd88343cae8af51d10596c0ceccaf22746678134
@@@ -6,7 -6,7 +6,8 @@@ package ae
  
  import (
        "crypto/cipher"
 +      "crypto/internal/boring"
+       "crypto/internal/subtle"
        "internal/cpu"
  )
  
index f68dfc9999721049161909f698ec8b6422c6093e,0000000000000000000000000000000000000000..26fdabb197ff968025da0bf73bf42891b1f5e410
mode 100644,000000..100644
--- /dev/null
@@@ -1,127 -1,0 +1,127 @@@
-       if runtime.GOOS == "nacl" {
-               // Times out on nacl (without BoringCrypto)
 +// 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.
 +
 +// Note: Can run these tests against the non-BoringCrypto
 +// version of the code by using "CGO_ENABLED=0 go test".
 +
 +package rsa
 +
 +import (
 +      "crypto"
 +      "crypto/rand"
 +      "encoding/asn1"
 +      "reflect"
 +      "runtime"
 +      "runtime/debug"
 +      "sync"
 +      "sync/atomic"
 +      "testing"
 +      "unsafe"
 +)
 +
 +func TestBoringASN1Marshal(t *testing.T) {
 +      k, err := GenerateKey(rand.Reader, 128)
 +      if err != nil {
 +              t.Fatal(err)
 +      }
 +      // This used to fail, because of the unexported 'boring' field.
 +      // Now the compiler hides it [sic].
 +      _, err = asn1.Marshal(k.PublicKey)
 +      if err != nil {
 +              t.Fatal(err)
 +      }
 +}
 +
 +func TestBoringDeepEqual(t *testing.T) {
 +      k, err := GenerateKey(rand.Reader, 128)
 +      if err != nil {
 +              t.Fatal(err)
 +      }
 +      k.boring = nil // probably nil already but just in case
 +      k2 := *k
 +      k2.boring = unsafe.Pointer(k) // anything not nil, for this test
 +      if !reflect.DeepEqual(k, &k2) {
 +              // compiler should be hiding the boring field from reflection
 +              t.Fatalf("DeepEqual compared boring fields")
 +      }
 +}
 +
 +func TestBoringVerify(t *testing.T) {
 +      // This changed behavior and broke golang.org/x/crypto/openpgp.
 +      // Go accepts signatures without leading 0 padding, while BoringCrypto does not.
 +      // So the Go wrappers must adapt.
 +      key := &PublicKey{
 +              N: bigFromHex("c4fdf7b40a5477f206e6ee278eaef888ca73bf9128a9eef9f2f1ddb8b7b71a4c07cfa241f028a04edb405e4d916c61d6beabc333813dc7b484d2b3c52ee233c6a79b1eea4e9cc51596ba9cd5ac5aeb9df62d86ea051055b79d03f8a4fa9f38386f5bd17529138f3325d46801514ea9047977e0829ed728e68636802796801be1"),
 +              E: 65537,
 +      }
 +
 +      hash := fromHex("019c5571724fb5d0e47a4260c940e9803ba05a44")
 +      paddedHash := fromHex("3021300906052b0e03021a05000414019c5571724fb5d0e47a4260c940e9803ba05a44")
 +
 +      // signature is one byte shorter than key.N.
 +      sig := fromHex("5edfbeb6a73e7225ad3cc52724e2872e04260d7daf0d693c170d8c4b243b8767bc7785763533febc62ec2600c30603c433c095453ede59ff2fcabeb84ce32e0ed9d5cf15ffcbc816202b64370d4d77c1e9077d74e94a16fb4fa2e5bec23a56d7a73cf275f91691ae1801a976fcde09e981a2f6327ac27ea1fecf3185df0d56")
 +
 +      err := VerifyPKCS1v15(key, 0, paddedHash, sig)
 +      if err != nil {
 +              t.Errorf("raw: %v", err)
 +      }
 +
 +      err = VerifyPKCS1v15(key, crypto.SHA1, hash, sig)
 +      if err != nil {
 +              t.Errorf("sha1: %v", err)
 +      }
 +}
 +
 +func TestBoringGenerateKey(t *testing.T) {
 +      k, err := GenerateKey(rand.Reader, 2048) // 2048 is smallest size BoringCrypto might kick in for
 +      if err != nil {
 +              t.Fatal(err)
 +      }
 +
 +      // Non-Boring GenerateKey always sets CRTValues to a non-nil (possibly empty) slice.
 +      if k.Precomputed.CRTValues == nil {
 +              t.Fatalf("GenerateKey: Precomputed.CRTValues = nil")
 +      }
 +}
 +
 +func TestBoringFinalizers(t *testing.T) {
-               t.Skip("skipping on nacl")
++      if runtime.GOOS == "nacl" || runtime.GOOS == "js" {
++              // Times out on nacl and js/wasm (without BoringCrypto)
 +              // but not clear why - probably consuming rand.Reader too quickly
 +              // and being throttled. Also doesn't really matter.
++              t.Skipf("skipping on %s/%s", runtime.GOOS, runtime.GOARCH)
 +      }
 +
 +      k, err := GenerateKey(rand.Reader, 2048)
 +      if err != nil {
 +              t.Fatal(err)
 +      }
 +
 +      // Run test with GOGC=10, to make bug more likely.
 +      // Without the KeepAlives, the loop usually dies after
 +      // about 30 iterations.
 +      defer debug.SetGCPercent(debug.SetGCPercent(10))
 +      for n := 0; n < 200; n++ {
 +              // Clear the underlying BoringCrypto object.
 +              atomic.StorePointer(&k.boring, nil)
 +
 +              // Race to create the underlying BoringCrypto object.
 +              // The ones that lose the race are prime candidates for
 +              // being GC'ed too early if the finalizers are not being
 +              // used correctly.
 +              var wg sync.WaitGroup
 +              for i := 0; i < 10; i++ {
 +                      wg.Add(1)
 +                      go func() {
 +                              defer wg.Done()
 +                              sum := make([]byte, 32)
 +                              _, err := SignPKCS1v15(rand.Reader, k, crypto.SHA256, sum)
 +                              if err != nil {
 +                                      panic(err) // usually caused by memory corruption, so hard stop
 +                              }
 +                      }()
 +              }
 +              wg.Wait()
 +      }
 +}
index f31f3f6bc8c4a2e67398ae73400e5a4e08c680c5,0000000000000000000000000000000000000000..2ac62a554053ce130405af1d466112fd0c80069a
mode 100644,000000..100644
--- /dev/null
@@@ -1,576 -1,0 +1,576 @@@
-       // 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" {
 +// 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))
 +}
 +
 +func isBoringSignatureScheme(alg SignatureScheme) bool {
 +      switch alg {
 +      default:
 +              return false
 +      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() {
 +              testingOnlyForceClientHelloSignatureAlgorithms = nil
 +      }()
 +
 +      for _, sigHash := range defaultSupportedSignatureAlgorithms {
 +              testingOnlyForceClientHelloSignatureAlgorithms = []SignatureScheme{sigHash}
 +
 +              t.Run(fmt.Sprintf("%v", sigHash), func(t *testing.T) {
 +                      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)
 +                              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, arm and wasm 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" || runtime.GOOS == "js" {
 +              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
 +}
Simple merge
index a76e4efac00edb3a37803f7cfa1e49e71e2149e9,7c8f0de6e82faa8a51ca6dc79bd8011ed5b74d3c..9a63eef5719960dd55ee83afde8872f7b7257c7e
@@@ -128,13 -127,15 +128,15 @@@ const 
        // Rest of these are reserved by the TLS spec
  )
  
- // Signature algorithms for TLS 1.2 (See RFC 5246, section A.4.1)
+ // Signature algorithms (for internal signaling use). Starting at 16 to avoid overlap with
+ // TLS 1.2 codepoints (RFC 5246, section A.4.1), with which these have nothing to do.
  const (
-       signatureRSA   uint8 = 1
-       signatureECDSA uint8 = 3
+       signaturePKCS1v15 uint8 = iota + 16
+       signatureECDSA
+       signatureRSAPSS
  )
  
 -// 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. 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.
Simple merge
index 5b1aa64166b30b783b084050e2ff3bb8709612e9,0d685927b37643bcfff59258b0251b9640909b2b..c5caab122457c12122dd177b763e3c26b7819e30
@@@ -520,59 -519,15 +519,15 @@@ func (hs *serverHandshakeState) doFullH
                }
  
                // Determine the signature type.
-               var signatureAlgorithm SignatureScheme
-               var sigType uint8
-               if certVerify.hasSignatureAndHash {
-                       signatureAlgorithm = certVerify.signatureAlgorithm
-                       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
-                       // algorithm was possible. Leave signatureAlgorithm
-                       // unset.
-                       switch pub.(type) {
-                       case *ecdsa.PublicKey:
-                               sigType = signatureECDSA
-                       case *rsa.PublicKey:
-                               sigType = signatureRSA
-                       }
 -              _, sigType, hashFunc, err := pickSignatureAlgorithm(pub, []SignatureScheme{certVerify.signatureAlgorithm}, supportedSignatureAlgorithms, c.vers)
++              _, sigType, hashFunc, err := pickSignatureAlgorithm(pub, []SignatureScheme{certVerify.signatureAlgorithm}, supportedSignatureAlgorithms(), c.vers)
+               if err != nil {
+                       c.sendAlert(alertIllegalParameter)
+                       return err
                }
  
-               switch key := pub.(type) {
-               case *ecdsa.PublicKey:
-                       if sigType != signatureECDSA {
-                               err = errors.New("tls: bad signature type for client's ECDSA certificate")
-                               break
-                       }
-                       ecdsaSig := new(ecdsaSignature)
-                       if _, err = asn1.Unmarshal(certVerify.signature, ecdsaSig); err != nil {
-                               break
-                       }
-                       if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
-                               err = errors.New("tls: ECDSA signature contained zero or negative values")
-                               break
-                       }
-                       var digest []byte
-                       if digest, _, err = hs.finishedHash.hashForClientCertificate(sigType, signatureAlgorithm, hs.masterSecret); err != nil {
-                               break
-                       }
-                       if !ecdsa.Verify(key, digest, ecdsaSig.R, ecdsaSig.S) {
-                               err = errors.New("tls: ECDSA verification failure")
-                       }
-               case *rsa.PublicKey:
-                       if sigType != signatureRSA {
-                               err = errors.New("tls: bad signature type for client's RSA certificate")
-                               break
-                       }
-                       var digest []byte
-                       var hashFunc crypto.Hash
-                       if digest, hashFunc, err = hs.finishedHash.hashForClientCertificate(sigType, signatureAlgorithm, hs.masterSecret); err != nil {
-                               break
-                       }
-                       err = rsa.VerifyPKCS1v15(key, hashFunc, digest, certVerify.signature)
+               var digest []byte
+               if digest, err = hs.finishedHash.hashForClientCertificate(sigType, hashFunc, hs.masterSecret); err == nil {
+                       err = verifyHandshakeSignature(sigType, pub, hashFunc, digest, certVerify.signature)
                }
                if err != nil {
                        c.sendAlert(alertBadCertificate)
index 5d6dc21c6dedec80ad67463841a7dded711c5990,1e77facce07d1e298cd0d530cb69240c9165f61c..0754d1b389966b919b85880f3332ae7fbdfc3ea4
@@@ -247,17 -208,12 +208,12 @@@ NextCandidate
        serverECDHParams[3] = byte(len(ecdhePublic))
        copy(serverECDHParams[4:], ecdhePublic)
  
-       var signatureAlgorithm SignatureScheme
-       if ka.version >= VersionTLS12 {
-               var err error
-               signatureAlgorithm, err = pickTLS12HashForSignature(ka.sigType, clientHello.supportedSignatureAlgorithms)
-               if err != nil {
-                       return nil, err
-               }
+       priv, ok := cert.PrivateKey.(crypto.Signer)
+       if !ok {
+               return nil, errors.New("tls: certificate private key does not implement crypto.Signer")
        }
  
-       digest, hashFunc, err := hashForServerKeyExchange(ka.sigType, signatureAlgorithm, ka.version, clientHello.random, hello.random, serverECDHParams)
 -      signatureAlgorithm, sigType, hashFunc, err := pickSignatureAlgorithm(priv.Public(), clientHello.supportedSignatureAlgorithms, supportedSignatureAlgorithms, ka.version)
++      signatureAlgorithm, sigType, hashFunc, err := pickSignatureAlgorithm(priv.Public(), clientHello.supportedSignatureAlgorithms, supportedSignatureAlgorithms(), ka.version)
        if err != nil {
                return nil, err
        }
index ff04b9e9825f708a9f29ac4ba9567aba91d9a593,29dbe47d29d4720821f5eca47b185e831232f82e..08ab218610e22a2a7c3b0776c3ef7498b1133db1
@@@ -99,34 -99,29 +99,36 @@@ var pkgDeps = map[string][]string
        // L3 adds reflection and some basic utility packages
        // and interface definitions, but nothing that makes
        // system calls.
-       "crypto":              {"L2", "hash"}, // interfaces
-       "crypto/cipher":       {"L2", "crypto/subtle"},
-       "crypto/subtle":       {},
-       "encoding/base32":     {"L2"},
-       "encoding/base64":     {"L2", "encoding/binary"},
-       "encoding/binary":     {"L2", "reflect"},
-       "hash":                {"L2"}, // interfaces
-       "hash/adler32":        {"L2", "hash"},
-       "hash/crc32":          {"L2", "hash"},
-       "hash/crc64":          {"L2", "hash"},
-       "hash/fnv":            {"L2", "hash"},
-       "image":               {"L2", "image/color"}, // interfaces
-       "image/color":         {"L2"},                // interfaces
-       "image/color/palette": {"L2", "image/color"},
-       "reflect":             {"L2"},
-       "sort":                {"reflect"},
+       "crypto":                 {"L2", "hash"}, // interfaces
+       "crypto/cipher":          {"L2", "crypto/subtle", "crypto/internal/subtle"},
+       "crypto/internal/subtle": {"unsafe", "reflect"}, // reflect behind a appengine tag
+       "crypto/subtle":          {},
+       "encoding/base32":        {"L2"},
+       "encoding/base64":        {"L2", "encoding/binary"},
+       "encoding/binary":        {"L2", "reflect"},
+       "hash":                   {"L2"}, // interfaces
+       "hash/adler32":           {"L2", "hash"},
+       "hash/crc32":             {"L2", "hash"},
+       "hash/crc64":             {"L2", "hash"},
+       "hash/fnv":               {"L2", "hash"},
+       "image":                  {"L2", "image/color"}, // interfaces
+       "image/color":            {"L2"},                // interfaces
+       "image/color/palette":    {"L2", "image/color"},
+       "reflect":                {"L2"},
+       "sort":                   {"reflect"},
  
 +      "crypto/internal/boring":         {"L2", "C", "crypto", "crypto/cipher", "crypto/internal/boring/sig", "crypto/subtle", "encoding/asn1", "hash", "math/big"},
 +      "crypto/internal/boring/fipstls": {"sync/atomic"},
 +      "crypto/internal/cipherhw":       {"crypto/internal/boring"},
 +      "crypto/tls/fipsonly":            {"crypto/internal/boring/fipstls", "crypto/internal/boring/sig"},
 +
        "L3": {
                "L2",
                "crypto",
                "crypto/cipher",
 +              "crypto/internal/boring",
 +              "crypto/internal/boring/fipstls",
+               "crypto/internal/subtle",
                "crypto/subtle",
                "encoding/base32",
                "encoding/base64",
        "go/types":                  {"L4", "GOPARSER", "container/heap", "go/constant"},
  
        // One of a kind.
--      "archive/tar":              {"L4", "OS", "syscall", "os/user"},
--      "archive/zip":              {"L4", "OS", "compress/flate"},
--      "container/heap":           {"sort"},
--      "compress/bzip2":           {"L4"},
--      "compress/flate":           {"L4"},
--      "compress/gzip":            {"L4", "compress/flate"},
--      "compress/lzw":             {"L4"},
--      "compress/zlib":            {"L4", "compress/flate"},
--      "context":                  {"errors", "fmt", "reflect", "sync", "time"},
--      "database/sql":             {"L4", "container/list", "context", "database/sql/driver", "database/sql/internal"},
--      "database/sql/driver":      {"L4", "context", "time", "database/sql/internal"},
--      "debug/dwarf":              {"L4"},
--      "debug/elf":                {"L4", "OS", "debug/dwarf", "compress/zlib"},
--      "debug/gosym":              {"L4"},
-       "debug/macho":              {"L4", "OS", "debug/dwarf"},
-       "debug/pe":                 {"L4", "OS", "debug/dwarf"},
 -      "debug/macho":              {"L4", "OS", "debug/dwarf", "compress/zlib"},
 -      "debug/pe":                 {"L4", "OS", "debug/dwarf", "compress/zlib"},
--      "debug/plan9obj":           {"L4", "OS"},
--      "encoding":                 {"L4"},
--      "encoding/ascii85":         {"L4"},
--      "encoding/asn1":            {"L4", "math/big"},
--      "encoding/csv":             {"L4"},
--      "encoding/gob":             {"L4", "OS", "encoding"},
--      "encoding/hex":             {"L4"},
--      "encoding/json":            {"L4", "encoding"},
--      "encoding/pem":             {"L4"},
--      "encoding/xml":             {"L4", "encoding"},
--      "flag":                     {"L4", "OS"},
--      "go/build":                 {"L4", "OS", "GOPARSER"},
--      "html":                     {"L4"},
--      "image/draw":               {"L4", "image/internal/imageutil"},
--      "image/gif":                {"L4", "compress/lzw", "image/color/palette", "image/draw"},
--      "image/internal/imageutil": {"L4"},
--      "image/jpeg":               {"L4", "image/internal/imageutil"},
--      "image/png":                {"L4", "compress/zlib"},
--      "index/suffixarray":        {"L4", "regexp"},
--      "internal/singleflight":    {"sync"},
--      "internal/trace":           {"L4", "OS"},
--      "math/big":                 {"L4"},
--      "mime":                     {"L4", "OS", "syscall", "internal/syscall/windows/registry"},
--      "mime/quotedprintable":     {"L4"},
--      "net/internal/socktest":    {"L4", "OS", "syscall", "internal/syscall/windows"},
--      "net/url":                  {"L4"},
--      "plugin":                   {"L0", "OS", "CGO"},
++      "archive/tar":                    {"L4", "OS", "syscall", "os/user"},
++      "archive/zip":                    {"L4", "OS", "compress/flate"},
++      "container/heap":                 {"sort"},
++      "compress/bzip2":                 {"L4"},
++      "compress/flate":                 {"L4"},
++      "compress/gzip":                  {"L4", "compress/flate"},
++      "compress/lzw":                   {"L4"},
++      "compress/zlib":                  {"L4", "compress/flate"},
++      "context":                        {"errors", "fmt", "reflect", "sync", "time"},
++      "database/sql":                   {"L4", "container/list", "context", "database/sql/driver", "database/sql/internal"},
++      "database/sql/driver":            {"L4", "context", "time", "database/sql/internal"},
++      "debug/dwarf":                    {"L4"},
++      "debug/elf":                      {"L4", "OS", "debug/dwarf", "compress/zlib"},
++      "debug/gosym":                    {"L4"},
++      "debug/macho":                    {"L4", "OS", "debug/dwarf", "compress/zlib"},
++      "debug/pe":                       {"L4", "OS", "debug/dwarf", "compress/zlib"},
++      "debug/plan9obj":                 {"L4", "OS"},
++      "encoding":                       {"L4"},
++      "encoding/ascii85":               {"L4"},
++      "encoding/asn1":                  {"L4", "math/big"},
++      "encoding/csv":                   {"L4"},
++      "encoding/gob":                   {"L4", "OS", "encoding"},
++      "encoding/hex":                   {"L4"},
++      "encoding/json":                  {"L4", "encoding"},
++      "encoding/pem":                   {"L4"},
++      "encoding/xml":                   {"L4", "encoding"},
++      "flag":                           {"L4", "OS"},
++      "go/build":                       {"L4", "OS", "GOPARSER"},
++      "html":                           {"L4"},
++      "image/draw":                     {"L4", "image/internal/imageutil"},
++      "image/gif":                      {"L4", "compress/lzw", "image/color/palette", "image/draw"},
++      "image/internal/imageutil":       {"L4"},
++      "image/jpeg":                     {"L4", "image/internal/imageutil"},
++      "image/png":                      {"L4", "compress/zlib"},
++      "index/suffixarray":              {"L4", "regexp"},
++      "internal/singleflight":          {"sync"},
++      "internal/trace":                 {"L4", "OS"},
++      "math/big":                       {"L4"},
++      "mime":                           {"L4", "OS", "syscall", "internal/syscall/windows/registry"},
++      "mime/quotedprintable":           {"L4"},
++      "net/internal/socktest":          {"L4", "OS", "syscall", "internal/syscall/windows"},
++      "net/url":                        {"L4"},
++      "plugin":                         {"L0", "OS", "CGO"},
        "runtime/pprof/internal/profile": {"L4", "OS", "compress/gzip", "regexp"},
        "testing/internal/testdeps":      {"L4", "internal/testlog", "runtime/pprof", "regexp"},
        "text/scanner":                   {"L4", "OS"},