--- /dev/null
- func supportedSignatureAlgorithms() []SignatureScheme {
+// 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.
++func supportedSignatureAlgorithms(version uint16) []SignatureScheme {
+ all := defaultSupportedSignatureAlgorithms
++ if version < VersionTLS13 {
++ all = defaultSupportedSignatureAlgorithmsTLS12
++ }
+ if !needFIPS() {
+ return all
+ }
+ i := 0
+ for i < len(all) && all[i] != PKCS1WithSHA1 {
+ i++
+ }
+ return all[:i]
+}
+
+var testingOnlyForceClientHelloSignatureAlgorithms []SignatureScheme
runServerTestTLS13(t, test)
}
- testSupportedSignatureAlgorithmsTLS12 := supportedSignatureAlgorithmsTLS12
- defer func() { supportedSignatureAlgorithmsTLS12 = testSupportedSignatureAlgorithmsTLS12 }()
- supportedSignatureAlgorithmsTLS12 = savedSupportedSignatureAlgorithmsTLS12
+ func TestHandshakeServerPSSDisabled(t *testing.T) {
+ test := &serverTest{
+ name: "RSA-PSS-Disabled",
+ command: []string{"openssl", "s_client", "-no_ticket"},
+ wait: true,
+ }
+
+ // Restore the default signature algorithms, disabling RSA-PSS in TLS 1.2,
+ // and check that handshakes still work.
++ testSupportedSignatureAlgorithmsTLS12 := defaultSupportedSignatureAlgorithmsTLS12
++ defer func() { defaultSupportedSignatureAlgorithmsTLS12 = testSupportedSignatureAlgorithmsTLS12 }()
++ defaultSupportedSignatureAlgorithmsTLS12 = savedSupportedSignatureAlgorithmsTLS12
+
+ runServerTestTLS12(t, test)
+ runServerTestTLS13(t, test)
+
+ test = &serverTest{
+ name: "RSA-PSS-Disabled-Required",
+ command: []string{"openssl", "s_client", "-no_ticket", "-sigalgs", "rsa_pss_rsae_sha256"},
+ wait: true,
+
+ expectHandshakeErrorIncluding: "peer doesn't support any common signature algorithms",
+ }
+
+ runServerTestTLS12(t, test)
+ }
+
func benchmarkHandshakeServer(b *testing.B, version uint16, cipherSuite uint16, curve CurveID, cert []byte, key crypto.PrivateKey) {
config := testConfig.Clone()
config.CipherSuites = []uint16{cipherSuite}
defer os.Remove(ecdsaCertPath)
ecdsaKeyPath = tempFile(clientECDSAKeyPEM)
defer os.Remove(ecdsaKeyPath)
- } else {
- t.Parallel()
}
- config := testConfig.Clone()
- config.ClientAuth = RequestClientCert
+ t.Run("Normal", func(t *testing.T) {
+ config := testConfig.Clone()
+ config.ClientAuth = RequestClientCert
- test := &serverTest{
- name: "ClientAuthRequestedNotGiven",
- command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA"},
- config: config,
- }
- runServerTestTLS12(t, test)
- runServerTestTLS13(t, test)
+ test := &serverTest{
+ name: "ClientAuthRequestedNotGiven",
+ command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA"},
+ config: config,
+ }
+ runServerTestTLS12(t, test)
+ runServerTestTLS13(t, test)
- test = &serverTest{
- name: "ClientAuthRequestedAndGiven",
- command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA",
- "-cert", certPath, "-key", keyPath, "-sigalgs", "rsa_pss_rsae_sha256"},
- config: config,
- expectedPeerCerts: []string{clientCertificatePEM},
- }
- runServerTestTLS12(t, test)
- runServerTestTLS13(t, test)
+ config.ClientAuth = RequireAnyClientCert
- test = &serverTest{
- name: "ClientAuthRequestedAndECDSAGiven",
- command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA",
- "-cert", ecdsaCertPath, "-key", ecdsaKeyPath},
- config: config,
- expectedPeerCerts: []string{clientECDSACertificatePEM},
- }
- runServerTestTLS12(t, test)
- runServerTestTLS13(t, test)
+ test = &serverTest{
+ name: "ClientAuthRequestedAndGiven",
+ command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA",
+ "-cert", certPath, "-key", keyPath, "-sigalgs", "rsa_pss_rsae_sha256"},
+ config: config,
+ expectedPeerCerts: []string{clientCertificatePEM},
+ }
+ runServerTestTLS12(t, test)
+ runServerTestTLS13(t, test)
+
+ test = &serverTest{
+ name: "ClientAuthRequestedAndECDSAGiven",
+ command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA",
+ "-cert", ecdsaCertPath, "-key", ecdsaKeyPath},
+ config: config,
+ expectedPeerCerts: []string{clientECDSACertificatePEM},
+ }
+ runServerTestTLS12(t, test)
+ runServerTestTLS13(t, test)
+
+ test = &serverTest{
+ name: "ClientAuthRequestedAndPKCS1v15Given",
+ command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA",
+ "-cert", certPath, "-key", keyPath, "-sigalgs", "rsa_pkcs1_sha256"},
+ config: config,
+ expectedPeerCerts: []string{clientCertificatePEM},
+ }
+ runServerTestTLS12(t, test)
+ })
- test = &serverTest{
- name: "ClientAuthRequestedAndPKCS1v15Given",
- command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA",
- "-cert", certPath, "-key", keyPath, "-sigalgs", "rsa_pkcs1_sha256"},
- config: config,
- expectedPeerCerts: []string{clientCertificatePEM},
- }
- runServerTestTLS12(t, test)
+ // Restore the default signature algorithms, disabling RSA-PSS in TLS 1.2,
+ // and check that handshakes still work.
- testSupportedSignatureAlgorithmsTLS12 := supportedSignatureAlgorithmsTLS12
- defer func() { supportedSignatureAlgorithmsTLS12 = testSupportedSignatureAlgorithmsTLS12 }()
- supportedSignatureAlgorithmsTLS12 = savedSupportedSignatureAlgorithmsTLS12
++ testSupportedSignatureAlgorithmsTLS12 := defaultSupportedSignatureAlgorithmsTLS12
++ defer func() { defaultSupportedSignatureAlgorithmsTLS12 = testSupportedSignatureAlgorithmsTLS12 }()
++ defaultSupportedSignatureAlgorithmsTLS12 = savedSupportedSignatureAlgorithmsTLS12
+
+ t.Run("PSSDisabled", func(t *testing.T) {
+ config := testConfig.Clone()
+ config.ClientAuth = RequireAnyClientCert
+
+ test := &serverTest{
+ name: "ClientAuthRequestedAndGiven-PSS-Disabled",
+ command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA",
+ "-cert", certPath, "-key", keyPath},
+ config: config,
+ expectedPeerCerts: []string{clientCertificatePEM},
+ }
+ runServerTestTLS12(t, test)
+ runServerTestTLS13(t, test)
+
+ test = &serverTest{
+ name: "ClientAuthRequestedAndGiven-PSS-Disabled-Required",
+ command: []string{"openssl", "s_client", "-no_ticket", "-cipher", "AES128-SHA",
+ "-cert", certPath, "-key", keyPath, "-client_sigalgs", "rsa_pss_rsae_sha256"},
+ config: config,
+
+ expectHandshakeErrorIncluding: "client didn't provide a certificate",
+ }
+ runServerTestTLS12(t, test)
+ })
}
func TestSNIGivenOnFailure(t *testing.T) {
t.Error("cloned hash generated a different sum")
}
}
- testSupportedSignatureAlgorithmsTLS12 := supportedSignatureAlgorithmsTLS12
- defer func() { supportedSignatureAlgorithmsTLS12 = testSupportedSignatureAlgorithmsTLS12 }()
- supportedSignatureAlgorithmsTLS12 = savedSupportedSignatureAlgorithmsTLS12
+
+ func TestKeyTooSmallForRSAPSS(t *testing.T) {
+ clientConn, serverConn := localPipe(t)
+ client := Client(clientConn, testConfig)
+ cert, err := X509KeyPair([]byte(`-----BEGIN CERTIFICATE-----
+ MIIBcTCCARugAwIBAgIQGjQnkCFlUqaFlt6ixyz/tDANBgkqhkiG9w0BAQsFADAS
+ MRAwDgYDVQQKEwdBY21lIENvMB4XDTE5MDExODIzMjMyOFoXDTIwMDExODIzMjMy
+ OFowEjEQMA4GA1UEChMHQWNtZSBDbzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDd
+ ez1rFUDwax2HTxbcnFUP9AhcgEGMHVV2nn4VVEWFJB6I8C/Nkx0XyyQlrmFYBzEQ
+ nIPhKls4T0hFoLvjJnXpAgMBAAGjTTBLMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUE
+ DDAKBggrBgEFBQcDATAMBgNVHRMBAf8EAjAAMBYGA1UdEQQPMA2CC2V4YW1wbGUu
+ Y29tMA0GCSqGSIb3DQEBCwUAA0EAxDuUS+BrrS3c+h+k+fQPOmOScy6yTX9mHw0Q
+ KbucGamXYEy0URIwOdO0tQ3LHPc1YGvYSPwkDjkjqECs2Vm/AA==
+ -----END CERTIFICATE-----`), []byte(`-----BEGIN RSA PRIVATE KEY-----
+ MIIBOgIBAAJBAN17PWsVQPBrHYdPFtycVQ/0CFyAQYwdVXaefhVURYUkHojwL82T
+ HRfLJCWuYVgHMRCcg+EqWzhPSEWgu+MmdekCAwEAAQJBALjQYNTdXF4CFBbXwUz/
+ yt9QFDYT9B5WT/12jeGAe653gtYS6OOi/+eAkGmzg1GlRnw6fOfn+HYNFDORST7z
+ 4j0CIQDn2xz9hVWQEu9ee3vecNT3f60huDGTNoRhtqgweQGX0wIhAPSLj1VcRZEz
+ nKpbtU22+PbIMSJ+e80fmY9LIPx5N4HTAiAthGSimMR9bloz0EY3GyuUEyqoDgMd
+ hXxjuno2WesoJQIgemilbcALXpxsLmZLgcQ2KSmaVr7jb5ECx9R+hYKTw1sCIG4s
+ T+E0J8wlH24pgwQHzy7Ko2qLwn1b5PW8ecrlvP1g
+ -----END RSA PRIVATE KEY-----`))
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ done := make(chan struct{})
+ go func() {
+ config := testConfig.Clone()
+ config.Certificates = []Certificate{cert}
+ config.MinVersion = VersionTLS13
+ server := Server(serverConn, config)
+ err := server.Handshake()
+ if !strings.Contains(err.Error(), "key size too small for PSS signature") {
+ t.Errorf(`expected "key size too small for PSS signature", got %q`, err)
+ }
+ close(done)
+ }()
+ err = client.Handshake()
+ if !strings.Contains(err.Error(), "handshake failure") {
+ t.Errorf(`expected "handshake failure", got %q`, err)
+ }
+ <-done
+
+ // With RSA-PSS disabled and TLS 1.2, this should work.
+
++ testSupportedSignatureAlgorithmsTLS12 := defaultSupportedSignatureAlgorithmsTLS12
++ defer func() { defaultSupportedSignatureAlgorithmsTLS12 = testSupportedSignatureAlgorithmsTLS12 }()
++ defaultSupportedSignatureAlgorithmsTLS12 = savedSupportedSignatureAlgorithmsTLS12
+
+ serverConfig := testConfig.Clone()
+ serverConfig.Certificates = []Certificate{cert}
+ serverConfig.MaxVersion = VersionTLS12
+ testHandshake(t, testConfig, serverConfig)
+ }