runner: Remove the ability to configure multiple certificates

While we do want to add this to the shim and real TLS stack, we have no
need to configure this on the runner. This is a remnant of runner being
a production TLS stack. We only ever configure one certificate because
we know what we expect the peer to send.

Change-Id: Idaafc66a2a7f83a929a6a61c19b97cdef158c534
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/66647
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Bob Beck <bbe@google.com>
diff --git a/ssl/test/runner/common.go b/ssl/test/runner/common.go
index 5bb533d..64f7741 100644
--- a/ssl/test/runner/common.go
+++ b/ssl/test/runner/common.go
@@ -16,7 +16,6 @@
 	"io"
 	"math/big"
 	"os"
-	"strings"
 	"sync"
 	"time"
 
@@ -442,18 +441,9 @@
 	// If Time is nil, TLS uses time.Now.
 	Time func() time.Time
 
-	// Chains contains one or more certificate chains
-	// to present to the other side of the connection.
-	// Server configurations must include at least one certificate.
-	Chains []CertificateChain
-
-	// NameToChain maps from a certificate name to an element of
-	// Chains. Note that a certificate name can be of the form
-	// '*.example.com' and so doesn't have to be a domain name as such.
-	// See Config.BuildNameToCertificate
-	// The nil value causes the first element of Chains to be used
-	// for all connections.
-	NameToChain map[string]*CertificateChain
+	// Chain contains the certificate chain to present to the other side of
+	// the connection. Server configurations must include this field.
+	Chain *CertificateChain
 
 	// RootCAs defines the set of root certificate authorities
 	// that clients use when verifying server certificates.
@@ -2134,39 +2124,6 @@
 	return ret
 }
 
-// getCertificateForName returns the best certificate for the given name,
-// defaulting to the first element of c.Chains if there are no good
-// options.
-func (c *Config) getCertificateForName(name string) *CertificateChain {
-	if len(c.Chains) == 1 || c.NameToChain == nil {
-		// There's only one choice, so no point doing any work.
-		return &c.Chains[0]
-	}
-
-	name = strings.ToLower(name)
-	for len(name) > 0 && name[len(name)-1] == '.' {
-		name = name[:len(name)-1]
-	}
-
-	if cert, ok := c.NameToChain[name]; ok {
-		return cert
-	}
-
-	// try replacing labels in the name with wildcards until we get a
-	// match.
-	labels := strings.Split(name, ".")
-	for i := range labels {
-		labels[i] = "*"
-		candidate := strings.Join(labels, ".")
-		if cert, ok := c.NameToChain[candidate]; ok {
-			return cert
-		}
-	}
-
-	// If nothing matches, return the first certificate.
-	return &c.Chains[0]
-}
-
 func (c *Config) signSignatureAlgorithms() []signatureAlgorithm {
 	if c != nil && c.SignSignatureAlgorithms != nil {
 		return c.SignSignatureAlgorithms
@@ -2181,26 +2138,6 @@
 	return supportedSignatureAlgorithms
 }
 
-// BuildNameToCertificate parses c.Chains and builds c.NameToCertificate
-// from the CommonName and SubjectAlternateName fields of each of the leaf
-// certificates.
-func (c *Config) BuildNameToCertificate() {
-	c.NameToChain = make(map[string]*CertificateChain)
-	for i := range c.Chains {
-		cert := &c.Chains[i]
-		x509Cert, err := x509.ParseCertificate(cert.Certificate[0])
-		if err != nil {
-			continue
-		}
-		if len(x509Cert.Subject.CommonName) > 0 {
-			c.NameToChain[x509Cert.Subject.CommonName] = cert
-		}
-		for _, san := range x509Cert.DNSNames {
-			c.NameToChain[san] = cert
-		}
-	}
-}
-
 // A CertificateChain is a chain of one or more certificates, leaf first.
 type CertificateChain struct {
 	Certificate [][]byte
diff --git a/ssl/test/runner/handshake_client.go b/ssl/test/runner/handshake_client.go
index 9b57b59..4619456 100644
--- a/ssl/test/runner/handshake_client.go
+++ b/ssl/test/runner/handshake_client.go
@@ -1213,11 +1213,7 @@
 
 			hs.writeServerHash(certReq.marshal())
 
-			chainToSend, err = selectClientCertificate(c, certReq)
-			if err != nil {
-				return err
-			}
-
+			chainToSend = c.config.Chain
 			msg, err = c.readHandshake()
 			if err != nil {
 				return err
@@ -1702,11 +1698,7 @@
 
 		hs.writeServerHash(certReq.marshal())
 
-		chainToSend, err = selectClientCertificate(c, certReq)
-		if err != nil {
-			return err
-		}
-
+		chainToSend = c.config.Chain
 		msg, err = c.readHandshake()
 		if err != nil {
 			return err
@@ -1769,7 +1761,7 @@
 		}
 
 		// Determine the hash to sign.
-		privKey := c.config.Chains[0].PrivateKey
+		privKey := c.config.Chain.PrivateKey
 
 		if certVerify.hasSignatureAlgorithm {
 			certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, privKey, c.config, certReq.signatureAlgorithms)
@@ -2400,23 +2392,6 @@
 	hs.finishedHash.WriteHandshake(msg, hs.c.recvHandshakeSeq-1)
 }
 
-// selectClientCertificate selects a certificate for use with the given
-// certificate, or none if none match. It may return a particular certificate or
-// nil on success, or an error on internal error.
-func selectClientCertificate(c *Conn, certReq *certificateRequestMsg) (*CertificateChain, error) {
-	if len(c.config.Chains) == 0 {
-		return nil, nil
-	}
-
-	// The test is assumed to have configured the certificate it meant to
-	// send.
-	if len(c.config.Chains) > 1 {
-		return nil, errors.New("tls: multiple certificates configured")
-	}
-
-	return &c.config.Chains[0], nil
-}
-
 // clientSessionCacheKey returns a key used to cache sessionTickets that could
 // be used to resume previously negotiated TLS sessions with a server.
 func clientSessionCacheKey(serverAddr net.Addr, config *Config) string {
diff --git a/ssl/test/runner/handshake_server.go b/ssl/test/runner/handshake_server.go
index 8ad49ca..d3f6392 100644
--- a/ssl/test/runner/handshake_server.go
+++ b/ssl/test/runner/handshake_server.go
@@ -1587,14 +1587,11 @@
 	if len(hs.clientHello.serverName) > 0 {
 		c.serverName = hs.clientHello.serverName
 	}
-	if len(config.Chains) == 0 {
+	if config.Chain == nil {
 		c.sendAlert(alertInternalError)
 		return errors.New("tls: no certificates configured")
 	}
-	hs.cert = &config.Chains[0]
-	if len(hs.clientHello.serverName) > 0 {
-		hs.cert = config.getCertificateForName(hs.clientHello.serverName)
-	}
+	hs.cert = config.Chain
 	if expected := c.config.Bugs.ExpectServerName; expected != "" && expected != hs.clientHello.serverName {
 		return fmt.Errorf("tls: unexpected server name: wanted %q, got %q", expected, hs.clientHello.serverName)
 	}
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index d711c35..c5554dc 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -1346,8 +1346,8 @@
 		if test.resumeConfig != nil {
 			resumeConfig = *test.resumeConfig
 			resumeConfig.Rand = config.Rand
-			if resumeConfig.Chains == nil {
-				resumeConfig.Chains = config.Chains
+			if resumeConfig.Chain == nil {
+				resumeConfig.Chain = config.Chain
 			}
 		} else {
 			resumeConfig = config
@@ -1596,17 +1596,11 @@
 		flags = append(flags, "-write-settings", transcriptPrefix)
 	}
 
-	if test.testType == clientTest {
-		if len(test.config.Chains) == 0 {
-			test.config.Chains = []CertificateChain{rsaCertificate}
-		}
-
-		rootFiles := make([]string, 0, len(test.config.Chains))
-		for _, c := range test.config.Chains {
-			rootFiles = append(rootFiles, c.RootPath)
-		}
-
-		flags = append(flags, "-trust-cert", strings.Join(rootFiles, ","))
+	if test.testType == clientTest && test.config.Chain == nil {
+		test.config.Chain = &rsaCertificate
+	}
+	if test.config.Chain != nil {
+		flags = append(flags, "-trust-cert", test.config.Chain.RootPath)
 	}
 
 	flags = append(flags, test.flags...)
@@ -2078,7 +2072,7 @@
 			name:     "ServerSkipCertificateVerify",
 			config: Config{
 				MaxVersion: VersionTLS12,
-				Chains:     []CertificateChain{rsaCertificate},
+				Chain:      &rsaCertificate,
 				Bugs: ProtocolBugs{
 					SkipCertificateVerify: true,
 				},
@@ -3576,14 +3570,14 @@
 	testCases = append(testCases, testCase{
 		name: "LargeMessage",
 		config: Config{
-			Chains: []CertificateChain{cert},
+			Chain: &cert,
 		},
 	})
 	testCases = append(testCases, testCase{
 		protocol: dtls,
 		name:     "LargeMessage-DTLS",
 		config: Config{
-			Chains: []CertificateChain{cert},
+			Chain: &cert,
 		},
 	})
 
@@ -3591,7 +3585,7 @@
 	testCases = append(testCases, testCase{
 		name: "LargeMessage-Reject",
 		config: Config{
-			Chains: []CertificateChain{cert},
+			Chain: &cert,
 		},
 		flags:         []string{"-max-cert-list", "16384"},
 		shouldFail:    true,
@@ -3601,7 +3595,7 @@
 		protocol: dtls,
 		name:     "LargeMessage-Reject-DTLS",
 		config: Config{
-			Chains: []CertificateChain{cert},
+			Chain: &cert,
 		},
 		flags:         []string{"-max-cert-list", "16384"},
 		shouldFail:    true,
@@ -3702,7 +3696,7 @@
 			MinVersion:           ver.version,
 			MaxVersion:           ver.version,
 			CipherSuites:         []uint16{suite.id},
-			Chains:               []CertificateChain{cert},
+			Chain:                &cert,
 			PreSharedKey:         []byte(psk),
 			PreSharedKeyIdentity: pskIdentity,
 			Bugs: ProtocolBugs{
@@ -3725,7 +3719,7 @@
 			MinVersion:           ver.version,
 			MaxVersion:           ver.version,
 			CipherSuites:         serverCipherSuites,
-			Chains:               []CertificateChain{cert},
+			Chain:                &cert,
 			PreSharedKey:         []byte(psk),
 			PreSharedKeyIdentity: pskIdentity,
 			Bugs: ProtocolBugs{
@@ -3752,7 +3746,7 @@
 			MinVersion:           ver.version,
 			MaxVersion:           ver.version,
 			CipherSuites:         []uint16{suite.id},
-			Chains:               []CertificateChain{cert},
+			Chain:                &cert,
 			PreSharedKey:         []byte(psk),
 			PreSharedKeyIdentity: pskIdentity,
 		},
@@ -3779,7 +3773,7 @@
 				MinVersion:           ver.version,
 				MaxVersion:           ver.version,
 				CipherSuites:         []uint16{suite.id},
-				Chains:               []CertificateChain{cert},
+				Chain:                &cert,
 				PreSharedKey:         []byte(psk),
 				PreSharedKeyIdentity: pskIdentity,
 			},
@@ -3919,7 +3913,7 @@
 		config: Config{
 			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-			Chains:       []CertificateChain{rsaCertificate},
+			Chain:        &rsaCertificate,
 			Bugs: ProtocolBugs{
 				SendCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
 			},
@@ -3932,7 +3926,7 @@
 		config: Config{
 			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
-			Chains:       []CertificateChain{ecdsaP256Certificate},
+			Chain:        &ecdsaP256Certificate,
 			Bugs: ProtocolBugs{
 				SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
 			},
@@ -3945,7 +3939,7 @@
 		config: Config{
 			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
-			Chains:       []CertificateChain{ed25519Certificate},
+			Chain:        &ed25519Certificate,
 			Bugs: ProtocolBugs{
 				SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
 			},
@@ -4111,7 +4105,7 @@
 				config: Config{
 					MaxVersion:   VersionTLS12,
 					CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
-					Chains:       []CertificateChain{ecdsaP256Certificate},
+					Chain:        &ecdsaP256Certificate,
 					Bugs: ProtocolBugs{
 						BadECDSAR: badR,
 						BadECDSAS: badS,
@@ -4124,7 +4118,7 @@
 				name: fmt.Sprintf("BadECDSA-%d-%d-TLS13", badR, badS),
 				config: Config{
 					MaxVersion: VersionTLS13,
-					Chains:     []CertificateChain{ecdsaP256Certificate},
+					Chain:      &ecdsaP256Certificate,
 					Bugs: ProtocolBugs{
 						BadECDSAR: badR,
 						BadECDSAS: badS,
@@ -4262,7 +4256,7 @@
 			config: Config{
 				MinVersion: ver.version,
 				MaxVersion: ver.version,
-				Chains:     []CertificateChain{rsaCertificate},
+				Chain:      &rsaCertificate,
 			},
 			flags: []string{"-require-any-client-certificate"},
 		})
@@ -4272,7 +4266,7 @@
 			config: Config{
 				MinVersion: ver.version,
 				MaxVersion: ver.version,
-				Chains:     []CertificateChain{ecdsaP256Certificate},
+				Chain:      &ecdsaP256Certificate,
 			},
 			flags: []string{"-require-any-client-certificate"},
 		})
@@ -4404,7 +4398,7 @@
 			config: Config{
 				MinVersion: ver.version,
 				MaxVersion: ver.version,
-				Chains:     []CertificateChain{rsaCertificate},
+				Chain:      &rsaCertificate,
 				Bugs: ProtocolBugs{
 					ExpectCertificateReqNames: caNames,
 				},
@@ -4421,7 +4415,7 @@
 			config: Config{
 				MinVersion: ver.version,
 				MaxVersion: ver.version,
-				Chains:     []CertificateChain{rsaCertificate},
+				Chain:      &rsaCertificate,
 				ClientAuth: RequireAnyClientCert,
 				ClientCAs:  certPool,
 			},
@@ -4473,7 +4467,7 @@
 		name:     "Null-Client-CA-List",
 		config: Config{
 			MaxVersion: VersionTLS12,
-			Chains:     []CertificateChain{rsaCertificate},
+			Chain:      &rsaCertificate,
 			Bugs: ProtocolBugs{
 				ExpectCertificateReqNames: [][]byte{},
 			},
@@ -4490,7 +4484,7 @@
 		name:     "TLS13-Empty-Client-CA-List",
 		config: Config{
 			MaxVersion: VersionTLS13,
-			Chains:     []CertificateChain{rsaCertificate},
+			Chain:      &rsaCertificate,
 			Bugs: ProtocolBugs{
 				ExpectNoCertificateAuthoritiesExtension: true,
 			},
@@ -5088,7 +5082,7 @@
 			name:     "ClientAuth-Server",
 			config: Config{
 				MaxVersion: VersionTLS12,
-				Chains:     []CertificateChain{rsaCertificate},
+				Chain:      &rsaCertificate,
 			},
 			flags: []string{"-require-any-client-certificate"},
 		})
@@ -5098,7 +5092,7 @@
 		name:     "ClientAuth-Server-TLS13",
 		config: Config{
 			MaxVersion: VersionTLS13,
-			Chains:     []CertificateChain{rsaCertificate},
+			Chain:      &rsaCertificate,
 		},
 		flags: []string{"-require-any-client-certificate"},
 	})
@@ -5224,7 +5218,7 @@
 			name:     "ClientOCSPCallback-Pass-" + vers.name,
 			config: Config{
 				MaxVersion: vers.version,
-				Chains:     []CertificateChain{rsaCertificate},
+				Chain:      &rsaCertificate,
 			},
 			flags: []string{
 				"-enable-ocsp-stapling",
@@ -5242,7 +5236,7 @@
 			name:     "ClientOCSPCallback-Fail-" + vers.name,
 			config: Config{
 				MaxVersion: vers.version,
-				Chains:     []CertificateChain{rsaCertificate},
+				Chain:      &rsaCertificate,
 			},
 			flags: []string{
 				"-enable-ocsp-stapling",
@@ -5262,7 +5256,7 @@
 			name:     "ClientOCSPCallback-FailNoStaple-" + vers.name,
 			config: Config{
 				MaxVersion: vers.version,
-				Chains:     []CertificateChain{certNoStaple},
+				Chain:      &certNoStaple,
 			},
 			flags: []string{
 				"-enable-ocsp-stapling",
@@ -5372,7 +5366,7 @@
 					name:     "CertificateVerificationSucceed" + suffix,
 					config: Config{
 						MaxVersion: vers.version,
-						Chains:     []CertificateChain{rsaCertificate},
+						Chain:      &rsaCertificate,
 					},
 					flags:         append([]string{"-expect-verify-result"}, flags...),
 					resumeSession: true,
@@ -5382,7 +5376,7 @@
 					name:     "CertificateVerificationFail" + suffix,
 					config: Config{
 						MaxVersion: vers.version,
-						Chains:     []CertificateChain{rsaCertificate},
+						Chain:      &rsaCertificate,
 					},
 					flags:              append([]string{"-verify-fail"}, flags...),
 					shouldFail:         true,
@@ -5395,7 +5389,7 @@
 					name:     "CertificateVerificationDoesNotFailOnResume" + suffix,
 					config: Config{
 						MaxVersion: vers.version,
-						Chains:     []CertificateChain{rsaCertificate},
+						Chain:      &rsaCertificate,
 					},
 					flags:         append([]string{"-on-resume-verify-fail"}, flags...),
 					resumeSession: true,
@@ -5406,7 +5400,7 @@
 						name:     "CertificateVerificationFailsOnResume" + suffix,
 						config: Config{
 							MaxVersion: vers.version,
-							Chains:     []CertificateChain{rsaCertificate},
+							Chain:      &rsaCertificate,
 						},
 						flags: append([]string{
 							"-on-resume-verify-fail",
@@ -5422,7 +5416,7 @@
 						name:     "CertificateVerificationPassesOnResume" + suffix,
 						config: Config{
 							MaxVersion: vers.version,
-							Chains:     []CertificateChain{rsaCertificate},
+							Chain:      &rsaCertificate,
 						},
 						flags: append([]string{
 							"-reverify-on-resume",
@@ -5553,7 +5547,7 @@
 			name:     "CertificateVerificationSoftFail-" + vers.name,
 			config: Config{
 				MaxVersion: vers.version,
-				Chains:     []CertificateChain{rsaCertificate},
+				Chain:      &rsaCertificate,
 			},
 			flags: []string{
 				"-verify-fail",
@@ -8413,7 +8407,7 @@
 				testType: clientTest,
 				config: Config{
 					MaxVersion: ver.version,
-					Chains:     []CertificateChain{emptySCTListCert},
+					Chain:      &emptySCTListCert,
 				},
 				flags: []string{
 					"-enable-signed-cert-timestamps",
@@ -8432,7 +8426,7 @@
 				testType: clientTest,
 				config: Config{
 					MaxVersion: ver.version,
-					Chains:     []CertificateChain{emptySCTCert},
+					Chain:      &emptySCTCert,
 				},
 				flags: []string{
 					"-enable-signed-cert-timestamps",
@@ -8665,7 +8659,7 @@
 		testType: serverTest,
 		config: Config{
 			MaxVersion: VersionTLS13,
-			Chains:     []CertificateChain{rsaCertificate},
+			Chain:      &rsaCertificate,
 			Bugs: ProtocolBugs{
 				SendExtensionOnCertificate: testOCSPExtension,
 			},
@@ -8695,7 +8689,7 @@
 		name: "IgnoreExtensionsOnIntermediates-TLS13",
 		config: Config{
 			MaxVersion: VersionTLS13,
-			Chains:     []CertificateChain{rsaChainCertificate},
+			Chain:      &rsaChainCertificate,
 			Bugs: ProtocolBugs{
 				// Send different values on the intermediate. This tests
 				// the intermediate's extensions do not override the
@@ -9757,7 +9751,7 @@
 		name: "Renegotiation-CertificateChange",
 		config: Config{
 			MaxVersion: VersionTLS12,
-			Chains:     []CertificateChain{rsaCertificate},
+			Chain:      &rsaCertificate,
 			Bugs: ProtocolBugs{
 				RenegotiationCertificate: &rsaChainCertificate,
 			},
@@ -9771,7 +9765,7 @@
 		name: "Renegotiation-CertificateChange-2",
 		config: Config{
 			MaxVersion: VersionTLS12,
-			Chains:     []CertificateChain{rsaCertificate},
+			Chain:      &rsaCertificate,
 			Bugs: ProtocolBugs{
 				RenegotiationCertificate: &rsa1024Certificate,
 			},
@@ -10045,7 +10039,7 @@
 					name:     prefix + "Verify" + suffix,
 					config: Config{
 						MaxVersion: ver.version,
-						Chains:     []CertificateChain{*alg.cert},
+						Chain:      alg.cert,
 						SignSignatureAlgorithms: []signatureAlgorithm{
 							alg.id,
 						},
@@ -10076,7 +10070,7 @@
 					name:     prefix + "VerifyDefault" + suffix,
 					config: Config{
 						MaxVersion: ver.version,
-						Chains:     []CertificateChain{*alg.cert},
+						Chain:      alg.cert,
 						SignSignatureAlgorithms: []signatureAlgorithm{
 							alg.id,
 						},
@@ -10105,7 +10099,7 @@
 					name:     prefix + "InvalidSignature" + suffix,
 					config: Config{
 						MaxVersion: ver.version,
-						Chains:     []CertificateChain{*alg.cert},
+						Chain:      alg.cert,
 						SignSignatureAlgorithms: []signatureAlgorithm{
 							alg.id,
 						},
@@ -10262,7 +10256,7 @@
 		name:     "Verify-ClientAuth-SignatureType",
 		config: Config{
 			MaxVersion: VersionTLS12,
-			Chains:     []CertificateChain{rsaCertificate},
+			Chain:      &rsaCertificate,
 			SignSignatureAlgorithms: []signatureAlgorithm{
 				signatureRSAPKCS1WithSHA256,
 			},
@@ -10282,7 +10276,7 @@
 		name:     "Verify-ClientAuth-SignatureType-TLS13",
 		config: Config{
 			MaxVersion: VersionTLS13,
-			Chains:     []CertificateChain{rsaCertificate},
+			Chain:      &rsaCertificate,
 			SignSignatureAlgorithms: []signatureAlgorithm{
 				signatureRSAPSSWithSHA256,
 			},
@@ -10440,7 +10434,7 @@
 		name:     "ClientAuth-Enforced",
 		config: Config{
 			MaxVersion: VersionTLS12,
-			Chains:     []CertificateChain{rsaCertificate},
+			Chain:      &rsaCertificate,
 			SignSignatureAlgorithms: []signatureAlgorithm{
 				signatureRSAPKCS1WithMD5,
 			},
@@ -10473,7 +10467,7 @@
 		name:     "ClientAuth-Enforced-TLS13",
 		config: Config{
 			MaxVersion: VersionTLS13,
-			Chains:     []CertificateChain{rsaCertificate},
+			Chain:      &rsaCertificate,
 			SignSignatureAlgorithms: []signatureAlgorithm{
 				signatureRSAPKCS1WithMD5,
 			},
@@ -10623,7 +10617,7 @@
 		config: Config{
 			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
-			Chains:       []CertificateChain{ecdsaP256Certificate},
+			Chain:        &ecdsaP256Certificate,
 		},
 		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
 		shouldFail:    true,
@@ -10635,7 +10629,7 @@
 		name: "CheckLeafCurve-TLS13",
 		config: Config{
 			MaxVersion: VersionTLS13,
-			Chains:     []CertificateChain{ecdsaP256Certificate},
+			Chain:      &ecdsaP256Certificate,
 		},
 		flags: []string{"-curves", strconv.Itoa(int(CurveP384))},
 	})
@@ -10646,7 +10640,7 @@
 		config: Config{
 			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
-			Chains:       []CertificateChain{ecdsaP256Certificate},
+			Chain:        &ecdsaP256Certificate,
 			SignSignatureAlgorithms: []signatureAlgorithm{
 				signatureECDSAWithP384AndSHA384,
 			},
@@ -10658,7 +10652,7 @@
 		name: "ECDSACurveMismatch-Verify-TLS13",
 		config: Config{
 			MaxVersion: VersionTLS13,
-			Chains:     []CertificateChain{ecdsaP256Certificate},
+			Chain:      &ecdsaP256Certificate,
 			SignSignatureAlgorithms: []signatureAlgorithm{
 				signatureECDSAWithP384AndSHA384,
 			},
@@ -10736,7 +10730,7 @@
 		name:     "NoEd25519-TLS11-ServerAuth-Verify",
 		config: Config{
 			MaxVersion: VersionTLS11,
-			Chains:     []CertificateChain{ed25519Certificate},
+			Chain:      &ed25519Certificate,
 			Bugs: ProtocolBugs{
 				// Sign with Ed25519 even though it is TLS 1.1.
 				SigningAlgorithmForLegacyVersions: signatureEd25519,
@@ -10761,7 +10755,7 @@
 		name:     "NoEd25519-TLS11-ClientAuth-Verify",
 		config: Config{
 			MaxVersion: VersionTLS11,
-			Chains:     []CertificateChain{ed25519Certificate},
+			Chain:      &ed25519Certificate,
 			Bugs: ProtocolBugs{
 				// Sign with Ed25519 even though it is TLS 1.1.
 				SigningAlgorithmForLegacyVersions: signatureEd25519,
@@ -10791,7 +10785,7 @@
 		testType: clientTest,
 		name:     "Ed25519DefaultDisable-NoAdvertise",
 		config: Config{
-			Chains: []CertificateChain{ed25519Certificate},
+			Chain: &ed25519Certificate,
 		},
 		shouldFail:         true,
 		expectedLocalError: "tls: no common signature algorithms",
@@ -10803,7 +10797,7 @@
 		testType: clientTest,
 		name:     "Ed25519DefaultDisable-NoAccept",
 		config: Config{
-			Chains: []CertificateChain{ed25519Certificate},
+			Chain: &ed25519Certificate,
 			Bugs: ProtocolBugs{
 				IgnorePeerSignatureAlgorithmPreferences: true,
 			},
@@ -10818,7 +10812,7 @@
 	testCases = append(testCases, testCase{
 		name: "VerifyPreferences-Advertised",
 		config: Config{
-			Chains: []CertificateChain{rsaCertificate},
+			Chain: &rsaCertificate,
 			SignSignatureAlgorithms: []signatureAlgorithm{
 				signatureRSAPSSWithSHA256,
 				signatureRSAPSSWithSHA384,
@@ -10836,7 +10830,7 @@
 	testCases = append(testCases, testCase{
 		name: "VerifyPreferences-NoCommonAlgorithms",
 		config: Config{
-			Chains: []CertificateChain{rsaCertificate},
+			Chain: &rsaCertificate,
 			SignSignatureAlgorithms: []signatureAlgorithm{
 				signatureRSAPSSWithSHA256,
 				signatureRSAPSSWithSHA512,
@@ -10853,7 +10847,7 @@
 	testCases = append(testCases, testCase{
 		name: "VerifyPreferences-Enforced",
 		config: Config{
-			Chains: []CertificateChain{rsaCertificate},
+			Chain: &rsaCertificate,
 			SignSignatureAlgorithms: []signatureAlgorithm{
 				signatureRSAPSSWithSHA256,
 				signatureRSAPSSWithSHA512,
@@ -10875,7 +10869,7 @@
 	testCases = append(testCases, testCase{
 		name: "VerifyPreferences-Ed25519",
 		config: Config{
-			Chains: []CertificateChain{ed25519Certificate},
+			Chain: &ed25519Certificate,
 		},
 		flags: []string{
 			"-verify-prefs", strconv.Itoa(int(signatureEd25519)),
@@ -10928,7 +10922,7 @@
 				name:     prefix + "NoVerify-RSA_PKCS1_MD5_SHA1",
 				config: Config{
 					MaxVersion: ver.version,
-					Chains:     []CertificateChain{rsaCertificate},
+					Chain:      &rsaCertificate,
 					Bugs: ProtocolBugs{
 						IgnorePeerSignatureAlgorithmPreferences: true,
 						AlwaysSignAsLegacyVersion:               true,
@@ -13105,7 +13099,7 @@
 				protocol: protocol,
 				name:     "ClientCertificate" + suffix,
 				config: Config{
-					Chains:     []CertificateChain{rsaCertificate},
+					Chain:      &rsaCertificate,
 					MaxVersion: VersionTLS12,
 				},
 				flags: []string{"-require-any-client-certificate"},
@@ -13119,7 +13113,7 @@
 				protocol: protocol,
 				name:     "CertificateVerify" + suffix,
 				config: Config{
-					Chains:     []CertificateChain{rsaCertificate},
+					Chain:      &rsaCertificate,
 					MaxVersion: VersionTLS12,
 				},
 				flags: []string{"-require-any-client-certificate"},
@@ -13295,7 +13289,7 @@
 				protocol: protocol,
 				name:     "TLS13-ClientCertificate" + suffix,
 				config: Config{
-					Chains:     []CertificateChain{rsaCertificate},
+					Chain:      &rsaCertificate,
 					MaxVersion: VersionTLS13,
 				},
 				flags: []string{"-require-any-client-certificate"},
@@ -13309,7 +13303,7 @@
 				protocol: protocol,
 				name:     "TLS13-ClientCertificateVerify" + suffix,
 				config: Config{
-					Chains:     []CertificateChain{rsaCertificate},
+					Chain:      &rsaCertificate,
 					MaxVersion: VersionTLS13,
 				},
 				flags: []string{"-require-any-client-certificate"},
@@ -14307,11 +14301,11 @@
 		name:     "EarlyData-RejectTicket-Client-TLS13",
 		config: Config{
 			MaxVersion: VersionTLS13,
-			Chains:     []CertificateChain{rsaCertificate},
+			Chain:      &rsaCertificate,
 		},
 		resumeConfig: &Config{
 			MaxVersion:             VersionTLS13,
-			Chains:                 []CertificateChain{ecdsaP256Certificate},
+			Chain:                  &ecdsaP256Certificate,
 			SessionTicketsDisabled: true,
 		},
 		resumeSession:           true,
@@ -14402,11 +14396,11 @@
 		name:     "EarlyData-HRR-RejectTicket-Client-TLS13",
 		config: Config{
 			MaxVersion: VersionTLS13,
-			Chains:     []CertificateChain{rsaCertificate},
+			Chain:      &rsaCertificate,
 		},
 		resumeConfig: &Config{
 			MaxVersion:             VersionTLS13,
-			Chains:                 []CertificateChain{ecdsaP256Certificate},
+			Chain:                  &ecdsaP256Certificate,
 			SessionTicketsDisabled: true,
 			Bugs: ProtocolBugs{
 				SendHelloRetryRequestCookie: []byte{1, 2, 3, 4},
@@ -15058,7 +15052,7 @@
 		config: Config{
 			MinVersion: VersionTLS13,
 			MaxVersion: VersionTLS13,
-			Chains:     []CertificateChain{rsaChainCertificate},
+			Chain:      &rsaChainCertificate,
 			Bugs: ProtocolBugs{
 				SkipCertificateVerify: true,
 			},
@@ -15080,7 +15074,7 @@
 		config: Config{
 			MinVersion: VersionTLS13,
 			MaxVersion: VersionTLS13,
-			Chains:     []CertificateChain{rsaChainCertificate},
+			Chain:      &rsaChainCertificate,
 			Bugs: ProtocolBugs{
 				SkipCertificateVerify: true,
 			},
@@ -15446,7 +15440,7 @@
 			config: Config{
 				MinVersion: ver.version,
 				MaxVersion: ver.version,
-				Chains:     []CertificateChain{rsaChainCertificate},
+				Chain:      &rsaChainCertificate,
 				ClientAuth: RequireAnyClientCert,
 			},
 			expectations: connectionExpectations{
@@ -15464,7 +15458,7 @@
 			config: Config{
 				MinVersion: ver.version,
 				MaxVersion: ver.version,
-				Chains:     []CertificateChain{rsaChainCertificate},
+				Chain:      &rsaChainCertificate,
 			},
 			expectations: connectionExpectations{
 				peerCertificate: &rsaChainCertificate,
@@ -15483,7 +15477,7 @@
 			config: Config{
 				MinVersion: ver.version,
 				MaxVersion: ver.version,
-				Chains:     []CertificateChain{garbageCertificate},
+				Chain:      &garbageCertificate,
 			},
 			shouldFail:         true,
 			expectedError:      ":CANNOT_PARSE_LEAF_CERT:",
@@ -15496,7 +15490,7 @@
 			config: Config{
 				MinVersion: ver.version,
 				MaxVersion: ver.version,
-				Chains:     []CertificateChain{garbageCertificate},
+				Chain:      &garbageCertificate,
 			},
 			flags:              []string{"-require-any-client-certificate"},
 			shouldFail:         true,
@@ -15533,7 +15527,7 @@
 			config: Config{
 				MinVersion: ver.version,
 				MaxVersion: ver.version,
-				Chains:     []CertificateChain{rsaCertificate},
+				Chain:      &rsaCertificate,
 			},
 			flags: []string{
 				"-verify-peer",
@@ -15554,7 +15548,7 @@
 			config: Config{
 				MinVersion: ver.version,
 				MaxVersion: ver.version,
-				Chains:     []CertificateChain{rsaCertificate},
+				Chain:      &rsaCertificate,
 			},
 			flags: []string{
 				"-verify-peer",
@@ -15574,7 +15568,7 @@
 			config: Config{
 				MinVersion: ver.version,
 				MaxVersion: ver.version,
-				Chains:     []CertificateChain{rsaCertificate},
+				Chain:      &rsaCertificate,
 			},
 			flags: []string{
 				"-verify-peer",
@@ -15622,7 +15616,7 @@
 			config: Config{
 				MinVersion: ver.version,
 				MaxVersion: ver.version,
-				Chains:     []CertificateChain{cert},
+				Chain:      &cert,
 			},
 			shouldFail:    true,
 			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
@@ -15634,7 +15628,7 @@
 			config: Config{
 				MinVersion: ver.version,
 				MaxVersion: ver.version,
-				Chains:     []CertificateChain{cert},
+				Chain:      &cert,
 			},
 			flags:         []string{"-require-any-client-certificate"},
 			shouldFail:    true,
@@ -15697,7 +15691,7 @@
 			config: Config{
 				MinVersion:   ver.version,
 				MaxVersion:   ver.version,
-				Chains:       []CertificateChain{encCert},
+				Chain:        &encCert,
 				CipherSuites: dsSuites,
 			},
 			shouldFail:    true,
@@ -15710,7 +15704,7 @@
 			config: Config{
 				MinVersion:   ver.version,
 				MaxVersion:   ver.version,
-				Chains:       []CertificateChain{dsCert},
+				Chain:        &dsCert,
 				CipherSuites: dsSuites,
 			},
 		})
@@ -15723,7 +15717,7 @@
 				config: Config{
 					MinVersion:   ver.version,
 					MaxVersion:   ver.version,
-					Chains:       []CertificateChain{encCert},
+					Chain:        &encCert,
 					CipherSuites: encSuites,
 				},
 			})
@@ -15734,7 +15728,7 @@
 				config: Config{
 					MinVersion:   ver.version,
 					MaxVersion:   ver.version,
-					Chains:       []CertificateChain{dsCert},
+					Chain:        &dsCert,
 					CipherSuites: encSuites,
 				},
 				shouldFail:    true,
@@ -15748,7 +15742,7 @@
 				config: Config{
 					MinVersion:   ver.version,
 					MaxVersion:   ver.version,
-					Chains:       []CertificateChain{dsCert},
+					Chain:        &dsCert,
 					CipherSuites: encSuites,
 				},
 				flags: []string{"-expect-key-usage-invalid", "-ignore-rsa-key-usage"},
@@ -15760,7 +15754,7 @@
 				config: Config{
 					MinVersion:   ver.version,
 					MaxVersion:   ver.version,
-					Chains:       []CertificateChain{encCert},
+					Chain:        &encCert,
 					CipherSuites: dsSuites,
 				},
 				flags: []string{"-expect-key-usage-invalid", "-ignore-rsa-key-usage"},
@@ -15775,7 +15769,7 @@
 				config: Config{
 					MinVersion:   ver.version,
 					MaxVersion:   ver.version,
-					Chains:       []CertificateChain{encCert},
+					Chain:        &encCert,
 					CipherSuites: dsSuites,
 				},
 				flags:         []string{"-ignore-rsa-key-usage"},
@@ -15791,7 +15785,7 @@
 			config: Config{
 				MinVersion: ver.version,
 				MaxVersion: ver.version,
-				Chains:     []CertificateChain{encCert},
+				Chain:      &encCert,
 			},
 			shouldFail:    true,
 			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
@@ -15804,7 +15798,7 @@
 			config: Config{
 				MinVersion: ver.version,
 				MaxVersion: ver.version,
-				Chains:     []CertificateChain{dsCert},
+				Chain:      &dsCert,
 			},
 			flags: []string{"-require-any-client-certificate"},
 		})
@@ -17339,7 +17333,7 @@
 			protocol: protocol,
 			name:     prefix + "ECH-Server-ClientAuth",
 			config: Config{
-				Chains:          []CertificateChain{rsaCertificate},
+				Chain:           &rsaCertificate,
 				ClientECHConfig: echConfig.ECHConfig,
 			},
 			flags: []string{
@@ -17358,7 +17352,7 @@
 			protocol: protocol,
 			name:     prefix + "ECH-Server-Decline-ClientAuth",
 			config: Config{
-				Chains:          []CertificateChain{rsaCertificate},
+				Chain:           &rsaCertificate,
 				ClientECHConfig: echConfig.ECHConfig,
 				Bugs: ProtocolBugs{
 					ExpectECHRetryConfigs: CreateECHConfigList(echConfig1.ECHConfig.Raw),
@@ -19050,7 +19044,7 @@
 			config: Config{
 				MinVersion: VersionTLS13,
 				MaxVersion: VersionTLS13,
-				Chains:     []CertificateChain{rsaCertificate},
+				Chain:      &rsaCertificate,
 			},
 			flags: []string{
 				"-allow-hint-mismatch",
@@ -19310,7 +19304,7 @@
 						MinVersion:   VersionTLS12,
 						MaxVersion:   maxVersion,
 						CipherSuites: []uint16{suite.id},
-						Chains:       []CertificateChain{cert},
+						Chain:        &cert,
 					},
 					flags: []string{
 						policy.flag,
@@ -19463,7 +19457,7 @@
 						MinVersion:              VersionTLS12,
 						MaxVersion:              maxVersion,
 						SignSignatureAlgorithms: []signatureAlgorithm{sigalg.id},
-						Chains:                  []CertificateChain{*sigalg.cert},
+						Chain:                   sigalg.cert,
 					},
 					flags: []string{
 						policy.flag,
diff --git a/ssl/test/runner/tls.go b/ssl/test/runner/tls.go
index bd94275..d283e77 100644
--- a/ssl/test/runner/tls.go
+++ b/ssl/test/runner/tls.go
@@ -73,7 +73,7 @@
 // The configuration config must be non-nil and must have
 // at least one certificate.
 func Listen(network, laddr string, config *Config) (net.Listener, error) {
-	if config == nil || len(config.Chains) == 0 {
+	if config == nil || config.Chain == nil {
 		return nil, errors.New("tls.Listen: no certificates in configuration")
 	}
 	l, err := net.Listen(network, laddr)