Source file src/crypto/tls/fips140_test.go

     1  // Copyright 2017 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package tls
     6  
     7  import (
     8  	"crypto/ecdsa"
     9  	"crypto/elliptic"
    10  	"crypto/fips140"
    11  	"crypto/internal/boring"
    12  	ifips140 "crypto/internal/fips140"
    13  	"crypto/rand"
    14  	"crypto/rsa"
    15  	"crypto/x509"
    16  	"crypto/x509/pkix"
    17  	"encoding/pem"
    18  	"fmt"
    19  	"internal/obscuretestdata"
    20  	"internal/testenv"
    21  	"math/big"
    22  	"net"
    23  	"os"
    24  	"regexp"
    25  	"runtime"
    26  	"strings"
    27  	"testing"
    28  	"time"
    29  )
    30  
    31  func allCipherSuitesIncludingTLS13() []uint16 {
    32  	s := allCipherSuites()
    33  	for _, suite := range cipherSuitesTLS13 {
    34  		s = append(s, suite.id)
    35  	}
    36  	return s
    37  }
    38  
    39  func isTLS13CipherSuite(id uint16) bool {
    40  	for _, suite := range cipherSuitesTLS13 {
    41  		if id == suite.id {
    42  			return true
    43  		}
    44  	}
    45  	return false
    46  }
    47  
    48  func generateKeyShare(group CurveID) keyShare {
    49  	ke, err := keyExchangeForCurveID(group)
    50  	if err != nil {
    51  		panic(err)
    52  	}
    53  	_, shares, err := ke.keyShares(rand.Reader)
    54  	if err != nil {
    55  		panic(err)
    56  	}
    57  	return shares[0]
    58  }
    59  
    60  func rerunWithFIPS140Enforced(t *testing.T) {
    61  	t.Helper()
    62  	if err := ifips140.Supported(); err != nil {
    63  		t.Skipf("test requires FIPS 140 mode: %v", err)
    64  	}
    65  	nameRegex := "^" + regexp.QuoteMeta(t.Name()) + "$"
    66  	cmd := testenv.Command(t, testenv.Executable(t), "-test.run="+nameRegex, "-test.v")
    67  	cmd.Env = append(cmd.Environ(), "GODEBUG=fips140=only")
    68  	out, err := cmd.CombinedOutput()
    69  	t.Logf("running with GODEBUG=fips140=only:\n%s", out)
    70  	if err != nil {
    71  		t.Errorf("fips140=only subprocess failed: %v", err)
    72  	}
    73  }
    74  
    75  var testConfigFIPS140 *Config
    76  
    77  func TestFIPSServerProtocolVersion(t *testing.T) {
    78  	test := func(t *testing.T, name string, v uint16, msg string) {
    79  		t.Run(name, func(t *testing.T) {
    80  			serverConfig := testConfigFIPS140.Clone()
    81  			serverConfig.MinVersion = VersionSSL30
    82  			clientConfig := testConfigFIPS140.Clone()
    83  			clientConfig.MinVersion = v
    84  			clientConfig.MaxVersion = v
    85  			_, _, err := testHandshake(t, clientConfig, serverConfig)
    86  			if msg == "" {
    87  				if err != nil {
    88  					t.Fatalf("got error: %v, expected success", err)
    89  				}
    90  			} else {
    91  				if err == nil {
    92  					t.Fatalf("got success, expected error")
    93  				}
    94  				if !strings.Contains(err.Error(), msg) {
    95  					t.Fatalf("got error %v, expected %q", err, msg)
    96  				}
    97  			}
    98  		})
    99  	}
   100  
   101  	runWithFIPSDisabled(t, func(t *testing.T) {
   102  		test(t, "VersionTLS10", VersionTLS10, "")
   103  		test(t, "VersionTLS11", VersionTLS11, "")
   104  		test(t, "VersionTLS12", VersionTLS12, "")
   105  		test(t, "VersionTLS13", VersionTLS13, "")
   106  	})
   107  
   108  	runWithFIPSEnabled(t, func(t *testing.T) {
   109  		test(t, "VersionTLS10", VersionTLS10, "supported versions")
   110  		test(t, "VersionTLS11", VersionTLS11, "supported versions")
   111  		test(t, "VersionTLS12", VersionTLS12, "")
   112  		test(t, "VersionTLS13", VersionTLS13, "")
   113  	})
   114  
   115  	if !fips140.Enforced() {
   116  		rerunWithFIPS140Enforced(t)
   117  	}
   118  }
   119  
   120  func isFIPSVersion(v uint16) bool {
   121  	return v == VersionTLS12 || v == VersionTLS13
   122  }
   123  
   124  func isFIPSCipherSuite(id uint16) bool {
   125  	name := CipherSuiteName(id)
   126  	if isTLS13CipherSuite(id) {
   127  		switch id {
   128  		case TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384:
   129  			return true
   130  		case TLS_CHACHA20_POLY1305_SHA256:
   131  			return false
   132  		default:
   133  			panic("unknown TLS 1.3 cipher suite: " + name)
   134  		}
   135  	}
   136  	switch id {
   137  	case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
   138  		TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
   139  		TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
   140  		TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
   141  		return true
   142  	case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
   143  		TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
   144  		// Only for the native module.
   145  		return !boring.Enabled
   146  	}
   147  	switch {
   148  	case strings.Contains(name, "CHACHA20"):
   149  		return false
   150  	case strings.HasSuffix(name, "_SHA"): // SHA-1
   151  		return false
   152  	case strings.HasPrefix(name, "TLS_RSA"): // RSA kex
   153  		return false
   154  	default:
   155  		panic("unknown cipher suite: " + name)
   156  	}
   157  }
   158  
   159  func isFIPSCurve(id CurveID) bool {
   160  	switch id {
   161  	case CurveP256, CurveP384, CurveP521:
   162  		return true
   163  	case X25519MLKEM768, SecP256r1MLKEM768, SecP384r1MLKEM1024:
   164  		// Only for the native module.
   165  		return !boring.Enabled
   166  	case X25519:
   167  		return false
   168  	default:
   169  		panic("unknown curve: " + id.String())
   170  	}
   171  }
   172  
   173  func isECDSA(id uint16) bool {
   174  	for _, suite := range cipherSuites {
   175  		if suite.id == id {
   176  			return suite.flags&suiteECSign == suiteECSign
   177  		}
   178  	}
   179  	return false // TLS 1.3 cipher suites are not tied to the signature algorithm.
   180  }
   181  
   182  func isFIPSSignatureScheme(alg SignatureScheme) bool {
   183  	switch alg {
   184  	case PKCS1WithSHA256,
   185  		ECDSAWithP256AndSHA256,
   186  		PKCS1WithSHA384,
   187  		ECDSAWithP384AndSHA384,
   188  		PKCS1WithSHA512,
   189  		ECDSAWithP521AndSHA512,
   190  		PSSWithSHA256,
   191  		PSSWithSHA384,
   192  		PSSWithSHA512:
   193  		return true
   194  	case Ed25519:
   195  		// Only for the native module.
   196  		return !boring.Enabled
   197  	case PKCS1WithSHA1, ECDSAWithSHA1:
   198  		return false
   199  	default:
   200  		panic("unknown signature scheme: " + alg.String())
   201  	}
   202  }
   203  
   204  func TestFIPSServerCipherSuites(t *testing.T) {
   205  	serverConfig := testConfigFIPS140.Clone()
   206  	serverConfig.Certificates = make([]Certificate, 1)
   207  
   208  	for _, id := range allCipherSuitesIncludingTLS13() {
   209  		if isECDSA(id) {
   210  			serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate}
   211  			serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey
   212  		} else {
   213  			serverConfig.Certificates[0].Certificate = [][]byte{testRSACertificate}
   214  			serverConfig.Certificates[0].PrivateKey = testRSAPrivateKey
   215  		}
   216  		serverConfig.BuildNameToCertificate()
   217  		t.Run(fmt.Sprintf("suite=%s", CipherSuiteName(id)), func(t *testing.T) {
   218  			clientHello := &clientHelloMsg{
   219  				vers:                         VersionTLS12,
   220  				random:                       make([]byte, 32),
   221  				cipherSuites:                 []uint16{id},
   222  				compressionMethods:           []uint8{compressionNone},
   223  				supportedCurves:              defaultCurvePreferences(),
   224  				keyShares:                    []keyShare{generateKeyShare(CurveP256)},
   225  				supportedPoints:              []uint8{pointFormatUncompressed},
   226  				supportedVersions:            []uint16{VersionTLS12},
   227  				supportedSignatureAlgorithms: allowedSignatureAlgorithmsFIPS,
   228  			}
   229  			if isTLS13CipherSuite(id) {
   230  				clientHello.supportedVersions = []uint16{VersionTLS13}
   231  			}
   232  
   233  			runWithFIPSDisabled(t, func(t *testing.T) {
   234  				testClientHello(t, serverConfig, clientHello)
   235  			})
   236  
   237  			runWithFIPSEnabled(t, func(t *testing.T) {
   238  				msg := ""
   239  				if !isFIPSCipherSuite(id) {
   240  					msg = "no cipher suite supported by both client and server"
   241  				}
   242  				testClientHelloFailure(t, serverConfig, clientHello, msg)
   243  			})
   244  		})
   245  	}
   246  
   247  	if !fips140.Enforced() {
   248  		rerunWithFIPS140Enforced(t)
   249  	}
   250  }
   251  
   252  func TestFIPSServerCurves(t *testing.T) {
   253  	serverConfig := testConfigFIPS140.Clone()
   254  	serverConfig.CurvePreferences = nil
   255  	serverConfig.BuildNameToCertificate()
   256  
   257  	for _, curveid := range defaultCurvePreferences() {
   258  		t.Run(fmt.Sprintf("curve=%v", curveid), func(t *testing.T) {
   259  			clientConfig := testConfigFIPS140.Clone()
   260  			clientConfig.CurvePreferences = []CurveID{curveid}
   261  
   262  			runWithFIPSDisabled(t, func(t *testing.T) {
   263  				if _, _, err := testHandshake(t, clientConfig, serverConfig); err != nil {
   264  					t.Fatalf("got error: %v, expected success", err)
   265  				}
   266  			})
   267  
   268  			// With fipstls forced, bad curves should be rejected.
   269  			runWithFIPSEnabled(t, func(t *testing.T) {
   270  				_, _, err := testHandshake(t, clientConfig, serverConfig)
   271  				if err != nil && isFIPSCurve(curveid) {
   272  					t.Fatalf("got error: %v, expected success", err)
   273  				} else if err == nil && !isFIPSCurve(curveid) {
   274  					t.Fatalf("got success, expected error")
   275  				}
   276  			})
   277  		})
   278  	}
   279  
   280  	if !fips140.Enforced() {
   281  		rerunWithFIPS140Enforced(t)
   282  	}
   283  }
   284  
   285  func fipsHandshake(t *testing.T, clientConfig, serverConfig *Config) (clientErr, serverErr error) {
   286  	c, s := localPipe(t)
   287  	client := Client(c, clientConfig)
   288  	server := Server(s, serverConfig)
   289  	done := make(chan error, 1)
   290  	go func() {
   291  		done <- client.Handshake()
   292  		c.Close()
   293  	}()
   294  	serverErr = server.Handshake()
   295  	s.Close()
   296  	clientErr = <-done
   297  	return
   298  }
   299  
   300  func TestFIPSServerSignatureAndHash(t *testing.T) {
   301  	defer func() {
   302  		testingOnlySupportedSignatureAlgorithms = nil
   303  	}()
   304  	defer func(godebug string) {
   305  		os.Setenv("GODEBUG", godebug)
   306  	}(os.Getenv("GODEBUG"))
   307  	os.Setenv("GODEBUG", "tlssha1=1")
   308  
   309  	for _, sigHash := range defaultSupportedSignatureAlgorithms() {
   310  		t.Run(fmt.Sprintf("%v", sigHash), func(t *testing.T) {
   311  			serverConfig := testConfigFIPS140.Clone()
   312  			serverConfig.Certificates = make([]Certificate, 1)
   313  
   314  			testingOnlySupportedSignatureAlgorithms = []SignatureScheme{sigHash}
   315  
   316  			sigType, _, _ := typeAndHashFromSignatureScheme(sigHash)
   317  			switch sigType {
   318  			case signaturePKCS1v15, signatureRSAPSS:
   319  				serverConfig.CipherSuites = []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256}
   320  				serverConfig.Certificates[0].Certificate = [][]byte{testRSAPSS2048Certificate}
   321  				serverConfig.Certificates[0].PrivateKey = testRSAPSS2048PrivateKey
   322  			case signatureEd25519:
   323  				serverConfig.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}
   324  				serverConfig.Certificates[0].Certificate = [][]byte{testEd25519Certificate}
   325  				serverConfig.Certificates[0].PrivateKey = testEd25519PrivateKey
   326  			case signatureECDSA:
   327  				serverConfig.CipherSuites = []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256}
   328  				serverConfig.Certificates[0].Certificate = [][]byte{testECDSACertificate}
   329  				serverConfig.Certificates[0].PrivateKey = testECDSAPrivateKey
   330  			}
   331  			serverConfig.BuildNameToCertificate()
   332  			// PKCS#1 v1.5 signature algorithms can't be used standalone in TLS
   333  			// 1.3, and the ECDSA ones bind to the curve used.
   334  			serverConfig.MaxVersion = VersionTLS12
   335  
   336  			runWithFIPSDisabled(t, func(t *testing.T) {
   337  				clientErr, serverErr := fipsHandshake(t, testConfigFIPS140, serverConfig)
   338  				if clientErr != nil {
   339  					t.Fatalf("expected handshake with %v to succeed; client error: %v; server error: %v", sigHash, clientErr, serverErr)
   340  				}
   341  			})
   342  
   343  			// With fipstls forced, bad curves should be rejected.
   344  			runWithFIPSEnabled(t, func(t *testing.T) {
   345  				clientErr, _ := fipsHandshake(t, testConfigFIPS140, serverConfig)
   346  				if isFIPSSignatureScheme(sigHash) {
   347  					if clientErr != nil {
   348  						t.Fatalf("expected handshake with %v to succeed; err=%v", sigHash, clientErr)
   349  					}
   350  				} else {
   351  					if clientErr == nil {
   352  						t.Fatalf("expected handshake with %v to fail, but it succeeded", sigHash)
   353  					}
   354  				}
   355  			})
   356  		})
   357  	}
   358  
   359  	if !fips140.Enforced() {
   360  		rerunWithFIPS140Enforced(t)
   361  	}
   362  }
   363  
   364  func TestFIPSClientHello(t *testing.T) {
   365  	runWithFIPSEnabled(t, testFIPSClientHello)
   366  }
   367  
   368  func testFIPSClientHello(t *testing.T) {
   369  	// Test that no matter what we put in the client config,
   370  	// the client does not offer non-FIPS configurations.
   371  
   372  	c, s := net.Pipe()
   373  	defer c.Close()
   374  	defer s.Close()
   375  
   376  	clientConfig := testConfigFIPS140.Clone()
   377  	// All sorts of traps for the client to avoid.
   378  	clientConfig.MinVersion = VersionSSL30
   379  	clientConfig.MaxVersion = VersionTLS13
   380  	clientConfig.CipherSuites = allCipherSuites()
   381  	clientConfig.CurvePreferences = defaultCurvePreferences()
   382  
   383  	go Client(c, clientConfig).Handshake()
   384  	srv := Server(s, testConfigFIPS140)
   385  	msg, err := srv.readHandshake(nil)
   386  	if err != nil {
   387  		t.Fatal(err)
   388  	}
   389  	hello, ok := msg.(*clientHelloMsg)
   390  	if !ok {
   391  		t.Fatalf("unexpected message type %T", msg)
   392  	}
   393  
   394  	if !isFIPSVersion(hello.vers) {
   395  		t.Errorf("client vers=%#x", hello.vers)
   396  	}
   397  	for _, v := range hello.supportedVersions {
   398  		if !isFIPSVersion(v) {
   399  			t.Errorf("client offered disallowed version %#x", v)
   400  		}
   401  	}
   402  	for _, id := range hello.cipherSuites {
   403  		if !isFIPSCipherSuite(id) {
   404  			t.Errorf("client offered disallowed suite %v", CipherSuiteName(id))
   405  		}
   406  	}
   407  	for _, id := range hello.supportedCurves {
   408  		if !isFIPSCurve(id) {
   409  			t.Errorf("client offered disallowed curve %v", id)
   410  		}
   411  	}
   412  	for _, sigHash := range hello.supportedSignatureAlgorithms {
   413  		if !isFIPSSignatureScheme(sigHash) {
   414  			t.Errorf("client offered disallowed signature-and-hash %v", sigHash)
   415  		}
   416  	}
   417  }
   418  
   419  func TestFIPSCertAlgs(t *testing.T) {
   420  	// arm and wasm time out generating keys. Nothing in this test is
   421  	// architecture-specific, so just don't bother on those.
   422  	if testenv.CPUIsSlow() {
   423  		t.Skipf("skipping on %s/%s because key generation takes too long", runtime.GOOS, runtime.GOARCH)
   424  	}
   425  
   426  	// Set up some roots, intermediate CAs, and leaf certs with various algorithms.
   427  	// X_Y is X signed by Y.
   428  	R1 := fipsCert(t, "R1", fipsRSAKey(t, 2048), nil, fipsCertCA|fipsCertFIPSOK)
   429  	R2 := fipsCert(t, "R2", fipsRSAKey(t, 1024), nil, fipsCertCA)
   430  	R3 := fipsCert(t, "R3", fipsRSAKey(t, 4096), nil, fipsCertCA|fipsCertFIPSOK)
   431  
   432  	M1_R1 := fipsCert(t, "M1_R1", fipsECDSAKey(t, elliptic.P256()), R1, fipsCertCA|fipsCertFIPSOK)
   433  	M2_R1 := fipsCert(t, "M2_R1", fipsECDSAKey(t, elliptic.P224()), R1, fipsCertCA)
   434  
   435  	I_R1 := fipsCert(t, "I_R1", fipsRSAKey(t, 3072), R1, fipsCertCA|fipsCertFIPSOK)
   436  	I_R2 := fipsCert(t, "I_R2", I_R1.key, R2, fipsCertCA|fipsCertFIPSOK)
   437  	I_M1 := fipsCert(t, "I_M1", I_R1.key, M1_R1, fipsCertCA|fipsCertFIPSOK)
   438  	I_M2 := fipsCert(t, "I_M2", I_R1.key, M2_R1, fipsCertCA|fipsCertFIPSOK)
   439  
   440  	I_R3 := fipsCert(t, "I_R3", fipsRSAKey(t, 3072), R3, fipsCertCA|fipsCertFIPSOK)
   441  	fipsCert(t, "I_R3", I_R3.key, R3, fipsCertCA|fipsCertFIPSOK)
   442  
   443  	L1_I := fipsCert(t, "L1_I", fipsECDSAKey(t, elliptic.P384()), I_R1, fipsCertLeaf|fipsCertFIPSOK)
   444  	L2_I := fipsCert(t, "L2_I", fipsRSAKey(t, 1024), I_R1, fipsCertLeaf)
   445  
   446  	// client verifying server cert
   447  	testServerCert := func(t *testing.T, desc string, pool *x509.CertPool, key any, list [][]byte, ok bool) {
   448  		clientConfig := testConfigFIPS140.Clone()
   449  		clientConfig.RootCAs = pool
   450  		clientConfig.InsecureSkipVerify = false
   451  		clientConfig.ServerName = "example.com"
   452  
   453  		serverConfig := testConfigFIPS140.Clone()
   454  		serverConfig.Certificates = []Certificate{{Certificate: list, PrivateKey: key}}
   455  		serverConfig.BuildNameToCertificate()
   456  
   457  		clientErr, _ := fipsHandshake(t, clientConfig, serverConfig)
   458  
   459  		if (clientErr == nil) == ok {
   460  			if ok {
   461  				t.Logf("%s: accept", desc)
   462  			} else {
   463  				t.Logf("%s: reject", desc)
   464  			}
   465  		} else {
   466  			if ok {
   467  				t.Errorf("%s: BAD reject (%v)", desc, clientErr)
   468  			} else {
   469  				t.Errorf("%s: BAD accept", desc)
   470  			}
   471  		}
   472  	}
   473  
   474  	// server verifying client cert
   475  	testClientCert := func(t *testing.T, desc string, pool *x509.CertPool, key any, list [][]byte, ok bool) {
   476  		clientConfig := testConfigFIPS140.Clone()
   477  		clientConfig.ServerName = "example.com"
   478  		clientConfig.Certificates = []Certificate{{Certificate: list, PrivateKey: key}}
   479  
   480  		serverConfig := testConfigFIPS140.Clone()
   481  		serverConfig.ClientCAs = pool
   482  		serverConfig.ClientAuth = RequireAndVerifyClientCert
   483  
   484  		_, serverErr := fipsHandshake(t, clientConfig, serverConfig)
   485  
   486  		if (serverErr == nil) == ok {
   487  			if ok {
   488  				t.Logf("%s: accept", desc)
   489  			} else {
   490  				t.Logf("%s: reject", desc)
   491  			}
   492  		} else {
   493  			if ok {
   494  				t.Errorf("%s: BAD reject (%v)", desc, serverErr)
   495  			} else {
   496  				t.Errorf("%s: BAD accept", desc)
   497  			}
   498  		}
   499  	}
   500  
   501  	// Run simple basic test with known answers before proceeding to
   502  	// exhaustive test with computed answers.
   503  	r1pool := x509.NewCertPool()
   504  	r1pool.AddCert(R1.cert)
   505  
   506  	runWithFIPSDisabled(t, func(t *testing.T) {
   507  		testServerCert(t, "basic", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, true)
   508  		testClientCert(t, "basic (client cert)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, true)
   509  	})
   510  
   511  	runWithFIPSEnabled(t, func(t *testing.T) {
   512  		testServerCert(t, "basic (fips)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, false)
   513  		testClientCert(t, "basic (fips, client cert)", r1pool, L2_I.key, [][]byte{L2_I.der, I_R1.der}, false)
   514  	})
   515  
   516  	if t.Failed() {
   517  		t.Fatal("basic test failed, skipping exhaustive test")
   518  	}
   519  
   520  	if testing.Short() {
   521  		t.Logf("basic test passed; skipping exhaustive test in -short mode")
   522  		return
   523  	}
   524  
   525  	for l := 1; l <= 2; l++ {
   526  		leaf := L1_I
   527  		if l == 2 {
   528  			leaf = L2_I
   529  		}
   530  		for i := 0; i < 64; i++ {
   531  			reachable := map[string]bool{leaf.parentOrg: true}
   532  			reachableFIPS := map[string]bool{leaf.parentOrg: leaf.fipsOK}
   533  			list := [][]byte{leaf.der}
   534  			listName := leaf.name
   535  			addList := func(cond int, c *fipsCertificate) {
   536  				if cond != 0 {
   537  					list = append(list, c.der)
   538  					listName += "," + c.name
   539  					if reachable[c.org] {
   540  						reachable[c.parentOrg] = true
   541  					}
   542  					if reachableFIPS[c.org] && c.fipsOK {
   543  						reachableFIPS[c.parentOrg] = true
   544  					}
   545  				}
   546  			}
   547  			addList(i&1, I_R1)
   548  			addList(i&2, I_R2)
   549  			addList(i&4, I_M1)
   550  			addList(i&8, I_M2)
   551  			addList(i&16, M1_R1)
   552  			addList(i&32, M2_R1)
   553  
   554  			for r := 1; r <= 3; r++ {
   555  				pool := x509.NewCertPool()
   556  				rootName := ","
   557  				shouldVerify := false
   558  				shouldVerifyFIPS := false
   559  				addRoot := func(cond int, c *fipsCertificate) {
   560  					if cond != 0 {
   561  						rootName += "," + c.name
   562  						pool.AddCert(c.cert)
   563  						if reachable[c.org] {
   564  							shouldVerify = true
   565  						}
   566  						if reachableFIPS[c.org] && c.fipsOK {
   567  							shouldVerifyFIPS = true
   568  						}
   569  					}
   570  				}
   571  				addRoot(r&1, R1)
   572  				addRoot(r&2, R2)
   573  				rootName = rootName[1:] // strip leading comma
   574  
   575  				runWithFIPSDisabled(t, func(t *testing.T) {
   576  					testServerCert(t, listName+"->"+rootName[1:], pool, leaf.key, list, shouldVerify)
   577  					testClientCert(t, listName+"->"+rootName[1:]+"(client cert)", pool, leaf.key, list, shouldVerify)
   578  				})
   579  
   580  				runWithFIPSEnabled(t, func(t *testing.T) {
   581  					testServerCert(t, listName+"->"+rootName[1:]+" (fips)", pool, leaf.key, list, shouldVerifyFIPS)
   582  					testClientCert(t, listName+"->"+rootName[1:]+" (fips, client cert)", pool, leaf.key, list, shouldVerifyFIPS)
   583  				})
   584  			}
   585  		}
   586  	}
   587  }
   588  
   589  const (
   590  	fipsCertCA = iota
   591  	fipsCertLeaf
   592  	fipsCertFIPSOK = 0x80
   593  )
   594  
   595  func fipsRSAKey(t *testing.T, size int) *rsa.PrivateKey {
   596  	k, err := rsa.GenerateKey(rand.Reader, size)
   597  	if err != nil {
   598  		t.Fatal(err)
   599  	}
   600  	return k
   601  }
   602  
   603  func fipsECDSAKey(t *testing.T, curve elliptic.Curve) *ecdsa.PrivateKey {
   604  	k, err := ecdsa.GenerateKey(curve, rand.Reader)
   605  	if err != nil {
   606  		t.Fatal(err)
   607  	}
   608  	return k
   609  }
   610  
   611  type fipsCertificate struct {
   612  	name      string
   613  	org       string
   614  	parentOrg string
   615  	der       []byte
   616  	cert      *x509.Certificate
   617  	key       any
   618  	fipsOK    bool
   619  }
   620  
   621  func fipsCert(t *testing.T, name string, key any, parent *fipsCertificate, mode int) *fipsCertificate {
   622  	org := name
   623  	parentOrg := ""
   624  	if i := strings.Index(org, "_"); i >= 0 {
   625  		org = org[:i]
   626  		parentOrg = name[i+1:]
   627  	}
   628  	tmpl := &x509.Certificate{
   629  		SerialNumber: big.NewInt(1),
   630  		Subject: pkix.Name{
   631  			Organization: []string{org},
   632  		},
   633  		NotBefore: time.Unix(0, 0),
   634  		NotAfter:  time.Unix(0, 0),
   635  
   636  		KeyUsage:              x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
   637  		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
   638  		BasicConstraintsValid: true,
   639  	}
   640  	if mode&^fipsCertFIPSOK == fipsCertLeaf {
   641  		tmpl.DNSNames = []string{"example.com"}
   642  	} else {
   643  		tmpl.IsCA = true
   644  		tmpl.KeyUsage |= x509.KeyUsageCertSign
   645  	}
   646  
   647  	var pcert *x509.Certificate
   648  	var pkey any
   649  	if parent != nil {
   650  		pcert = parent.cert
   651  		pkey = parent.key
   652  	} else {
   653  		pcert = tmpl
   654  		pkey = key
   655  	}
   656  
   657  	var pub any
   658  	var desc string
   659  	switch k := key.(type) {
   660  	case *rsa.PrivateKey:
   661  		pub = &k.PublicKey
   662  		desc = fmt.Sprintf("RSA-%d", k.N.BitLen())
   663  	case *ecdsa.PrivateKey:
   664  		pub = &k.PublicKey
   665  		desc = "ECDSA-" + k.Curve.Params().Name
   666  	default:
   667  		t.Fatalf("invalid key %T", key)
   668  	}
   669  
   670  	der, err := x509.CreateCertificate(rand.Reader, tmpl, pcert, pub, pkey)
   671  	if err != nil {
   672  		t.Fatal(err)
   673  	}
   674  	cert, err := x509.ParseCertificate(der)
   675  	if err != nil {
   676  		t.Fatal(err)
   677  	}
   678  
   679  	fipsOK := mode&fipsCertFIPSOK != 0
   680  	runWithFIPSEnabled(t, func(t *testing.T) {
   681  		if isCertificateAllowedFIPS(cert) != fipsOK {
   682  			t.Errorf("fipsAllowCert(cert with %s key) = %v, want %v", desc, !fipsOK, fipsOK)
   683  		}
   684  	})
   685  
   686  	return &fipsCertificate{name, org, parentOrg, der, cert, key, fipsOK}
   687  }
   688  
   689  // A self-signed test certificate with an RSA key of size 2048, for testing
   690  // RSA-PSS with SHA512. SAN of example.golang.
   691  var (
   692  	testRSAPSS2048Certificate []byte
   693  	testRSAPSS2048PrivateKey  *rsa.PrivateKey
   694  )
   695  
   696  func init() {
   697  	block, _ := pem.Decode(obscuretestdata.Rot13([]byte(`
   698  -----ORTVA PREGVSVPNGR-----
   699  ZVVP/mPPNrrtNjVONtVENYUUK/xu4+4mZH9QnemORpDjQDLWXbMVuipANDRYODNj
   700  RwRDZN4TN1HRPuZUDJAgMFOQomNrSj0kZGNkZQRkAGN0ZQInSj0lZQRlZwxkAGN0
   701  ZQInZOVkRQNBOtAIONbGO0SwoJHtD28jttRvZN0TPFdTFVo3QDRONDHNN4VOQjNj
   702  ttRXNbVONDPs8sx0A6vrPOK4VBIVsXvgg4xTpBDYrvzPsfwddUplfZVITRgSFZ6R
   703  4Nl141s/7VdqJ0HgVdAo4CKuEBVQ7lQkE284kY6KoPhi/g5uC3HpruLp3uzYvlIq
   704  ZxMDvMJgsHHWs/1dBgZ+buAt59YEJc4q+6vK0yn1WY3RjPVpxxAwW9uDoS7Co2PF
   705  +RF9Lb55XNnc8XBoycpE8ZOFA38odajwsDqPKiBRBwnz2UHkXmRSK5ZN+sN0zr4P
   706  vbPpPEYJXy+TbA9S8sNOsbM+G+2rny4QYhB95eKE8FeBVIOu3KSBe/EIuwgKpAIS
   707  MXpiQg6q68I6wNXNLXz5ayw9TCcq4i+eNtZONNTwHQOBZN4TN1HqQjRO/jDRNjVS
   708  bQNGOtAIUFHRQQNXOtteOtRSODpQNGNZOtAIUEZONs8RNwNNZOxTN1HqRDDFZOPP
   709  QzI4LJ1joTHhM29fLJ5aZN0TPFdTFVo3QDROPjHNN4VONDPBbLfIpSPOuobdr3JU
   710  qP6I7KKKRPzawu01e8u80li0AE379aFQ3pj2Z+UXinKlfJdey5uwTIXj0igjQ81e
   711  I4WmQh7VsVbt5z8+DAP+7YdQMfm88iQXBefblFIBzHPtzPXSKrj+YN+rB/vDRWGe
   712  7rafqqBrKWRc27Rq5iJ+xzJJ3Dztyp2Tjl8jSeZQVdaeaBmON4bPaQRtgKWg0mbt
   713  aEjosRZNJv1nDEl5qG9XN3FC9zb5FrGSFmTTUvR4f4tUHr7wifNSS2dtgQ6+jU6f
   714  m9o6fukaP7t5VyOXuV7FIO/Hdg2lqW+xU1LowZpVd6ANZ5rAZXtMhWe3+mjfFtju
   715  TAnR
   716  -----RAQ PREGVSVPNGR-----`)))
   717  	testRSAPSS2048Certificate = block.Bytes
   718  
   719  	block, _ = pem.Decode(obscuretestdata.Rot13([]byte(`
   720  -----ORTVA EFN CEVINGR XRL-----
   721  ZVVRcNVONNXPNDRNa/U5AQrbattI+PQyFUlbeorWOaQxP3bcta7V6du3ZeQPSEuY
   722  EHwBuBNZgrAK/+lXaIgSYFXwJ+Q14HGvN+8t8HqiBZF+y2jee/7rLG91UUbJUA4M
   723  v4fyKGWTHVzIeK1SPK/9nweGCdVGLBsF0IdrUshby9WJgFF9kZNvUWWQLlsLHTkr
   724  m29txiuRiJXBrFtTdsPwz5nKRsQNHwq/T6c8V30UDy7muQb2cgu1ZFfkOI+GNCaj
   725  AWahNbdNaNxF1vcsudQsEsUjNK6Tsx/gazcrNl7wirn10sRdmvSDLq1kGd/0ILL7
   726  I3QIEJFaYj7rariSrbjPtTPchM5L/Ew6KrY/djVQNDNONbVONDPAcZMvsq/it42u
   727  UqPiYhMnLF0E7FhaSycbKRfygTqYSfac0VsbWM/htSDOFNVVsYjZhzH6bKN1m7Hi
   728  98nVLI61QrCeGPQIQSOfUoAzC8WNb8JgohfRojq5mlbO7YLT2+pyxWxyJR73XdHd
   729  ezV+HWrlFpy2Tva7MGkOKm1JCOx9IjpajxrnKctNFVOJ23suRPZ9taLRRjnOrm5G
   730  6Zr8q1gUgLDi7ifXr7eb9j9/UXeEKrwdLXX1YkxusSevlI+z8YMWMa2aKBn6T3tS
   731  Ao8Dx1Hx5CHORAOzlZSWuG4Z/hhFd4LgZeeB2tv8D+sCuhTmp5FfuLXEOc0J4C5e
   732  zgIPgRSENbTONZRAOVSYeI2+UfTw0kLSnfXbi/DCr6UFGE1Uu2VMBAc+bX4bfmJR
   733  wOG4IpaVGzcy6gP1Jl4TpekwAtXVSMNw+1k1YHHYqbeKxhT8le0gNuT9mAlsJfFl
   734  CeFbiP0HIome8Wkkyn+xDIkRDDdJDkCyRIhY8xKnVQN6Ylg1Uchn2YiCNbTONADM
   735  p6Yd2G7+OkYkAqv2z8xMmrw5xtmOc/KqIfoSJEyroVK2XeSUfeUmG9CHx3QR1iMX
   736  Z6cmGg94aDuJFxQtPnj1FbuRyW3USVSjphfS1FWNp3cDrcq8ht6VLqycQZYgOw/C
   737  /5C6OIHgtb05R4+V/G3vLngztyDkGgyM0ExFI2yyNbTONYBKxXSK7nuCis0JxfQu
   738  hGshSBGCbbjtDT0RctJ0jEqPkrt/WYvp3yFQ0tfggDI2JfErpelJpknryEt10EzB
   739  38OobtzunS4kitfFihwBsvMGR8bX1G43Z+6AXfVyZY3LVYocH/9nWkCJl0f2QdQe
   740  pDWuMeyx+cmwON7Oas/HEqjkNbTNXE/PAj14Q+zeY3LYoovPKvlqdkIjki5cqMqm
   741  8guv3GApfJP4vTHEqpIdosHvaICqWvKr/Xnp3JTPrEWnSItoXNBkYgv1EO5ZxVut
   742  Q8rlhcOdx4J1Y1txekdfqw4GSykxjZljwy2R2F4LlD8COg6I04QbIEMfVXmdm+CS
   743  HvbaCd0PtLOPLKidvbWuCrjxBd/L5jeQOrMJ1SDX5DQ9J5Z8/5mkq4eqiWgwuoWc
   744  bBegiZqey6hcl9Um4OWQ3SKjISvCSR7wdrAdv0S21ivYkOCZZQ3HBQS6YY5RlYvE
   745  9I4kIZF8XKkit7ekfhdmZCfpIvnJHY6JAIOufQ2+92qUkFKmm5RWXD==
   746  -----RAQ EFN CEVINGR XRL-----`)))
   747  	var err error
   748  	testRSAPSS2048PrivateKey, err = x509.ParsePKCS1PrivateKey(block.Bytes)
   749  	if err != nil {
   750  		panic(err)
   751  	}
   752  }
   753  

View as plain text