• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (c) 2016, Google Inc.
2//
3// Permission to use, copy, modify, and/or distribute this software for any
4// purpose with or without fee is hereby granted, provided that the above
5// copyright notice and this permission notice appear in all copies.
6//
7// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15package runner
16
17import (
18	"bytes"
19	"crypto"
20	"crypto/ecdsa"
21	"crypto/ed25519"
22	"crypto/elliptic"
23	"crypto/rand"
24	"crypto/rsa"
25	"crypto/x509"
26	"crypto/x509/pkix"
27	_ "embed"
28	"encoding/base64"
29	"encoding/binary"
30	"encoding/hex"
31	"encoding/json"
32	"encoding/pem"
33	"errors"
34	"flag"
35	"fmt"
36	"io"
37	"math/big"
38	"net"
39	"os"
40	"os/exec"
41	"path/filepath"
42	"runtime"
43	"strconv"
44	"strings"
45	"sync"
46	"syscall"
47	"time"
48
49	"boringssl.googlesource.com/boringssl/ssl/test/runner/hpke"
50	"boringssl.googlesource.com/boringssl/util/testresult"
51	"golang.org/x/crypto/cryptobyte"
52)
53
54var (
55	useValgrind        = flag.Bool("valgrind", false, "If true, run code under valgrind")
56	useGDB             = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb")
57	useLLDB            = flag.Bool("lldb", false, "If true, run BoringSSL code under lldb")
58	useRR              = flag.Bool("rr-record", false, "If true, run BoringSSL code under `rr record`.")
59	waitForDebugger    = flag.Bool("wait-for-debugger", false, "If true, jobs will run one at a time and pause for a debugger to attach")
60	flagDebug          = flag.Bool("debug", false, "Hexdump the contents of the connection")
61	mallocTest         = flag.Int64("malloc-test", -1, "If non-negative, run each test with each malloc in turn failing from the given number onwards.")
62	mallocTestDebug    = flag.Bool("malloc-test-debug", false, "If true, ask bssl_shim to abort rather than fail a malloc. This can be used with a specific value for --malloc-test to identity the malloc failing that is causing problems.")
63	jsonOutput         = flag.String("json-output", "", "The file to output JSON results to.")
64	pipe               = flag.Bool("pipe", false, "If true, print status output suitable for piping into another program.")
65	testToRun          = flag.String("test", "", "Semicolon-separated patterns of tests to run, or empty to run all tests")
66	skipTest           = flag.String("skip", "", "Semicolon-separated patterns of tests to skip")
67	allowHintMismatch  = flag.String("allow-hint-mismatch", "", "Semicolon-separated patterns of tests where hints may mismatch")
68	numWorkersFlag     = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
69	shimPath           = flag.String("shim-path", "../../../build/ssl/test/bssl_shim", "The location of the shim binary.")
70	shimExtraFlags     = flag.String("shim-extra-flags", "", "Semicolon-separated extra flags to pass to the shim binary on each invocation.")
71	handshakerPath     = flag.String("handshaker-path", "../../../build/ssl/test/handshaker", "The location of the handshaker binary.")
72	fuzzer             = flag.Bool("fuzzer", false, "If true, tests against a BoringSSL built in fuzzer mode.")
73	transcriptDir      = flag.String("transcript-dir", "", "The directory in which to write transcripts.")
74	idleTimeout        = flag.Duration("idle-timeout", 15*time.Second, "The number of seconds to wait for a read or write to bssl_shim.")
75	deterministic      = flag.Bool("deterministic", false, "If true, uses a deterministic PRNG in the runner.")
76	allowUnimplemented = flag.Bool("allow-unimplemented", false, "If true, report pass even if some tests are unimplemented.")
77	looseErrors        = flag.Bool("loose-errors", false, "If true, allow shims to report an untranslated error code.")
78	shimConfigFile     = flag.String("shim-config", "", "A config file to use to configure the tests for this shim.")
79	includeDisabled    = flag.Bool("include-disabled", false, "If true, also runs disabled tests.")
80	repeatUntilFailure = flag.Bool("repeat-until-failure", false, "If true, the first selected test will be run repeatedly until failure.")
81)
82
83// ShimConfigurations is used with the “json” package and represents a shim
84// config file.
85type ShimConfiguration struct {
86	// DisabledTests maps from a glob-based pattern to a freeform string.
87	// The glob pattern is used to exclude tests from being run and the
88	// freeform string is unparsed but expected to explain why the test is
89	// disabled.
90	DisabledTests map[string]string
91
92	// ErrorMap maps from expected error strings to the correct error
93	// string for the shim in question. For example, it might map
94	// “:NO_SHARED_CIPHER:” (a BoringSSL error string) to something
95	// like “SSL_ERROR_NO_CYPHER_OVERLAP”.
96	ErrorMap map[string]string
97
98	// HalfRTTTickets is the number of half-RTT tickets the client should
99	// expect before half-RTT data when testing 0-RTT.
100	HalfRTTTickets int
101
102	// AllCurves is the list of all curve code points supported by the shim.
103	// This is currently used to control tests that enable all curves but may
104	// automatically disable tests in the future.
105	AllCurves []int
106}
107
108// Setup shimConfig defaults aligning with BoringSSL.
109var shimConfig ShimConfiguration = ShimConfiguration{
110	HalfRTTTickets: 2,
111}
112
113//go:embed rsa_2048_key.pem
114var rsa2048KeyPEM []byte
115
116//go:embed rsa_1024_key.pem
117var rsa1024KeyPEM []byte
118
119//go:embed ecdsa_p224_key.pem
120var ecdsaP224KeyPEM []byte
121
122//go:embed ecdsa_p256_key.pem
123var ecdsaP256KeyPEM []byte
124
125//go:embed ecdsa_p384_key.pem
126var ecdsaP384KeyPEM []byte
127
128//go:embed ecdsa_p521_key.pem
129var ecdsaP521KeyPEM []byte
130
131//go:embed ed25519_key.pem
132var ed25519KeyPEM []byte
133
134//go:embed channel_id_key.pem
135var channelIDKeyPEM []byte
136
137var (
138	rsa1024Key rsa.PrivateKey
139	rsa2048Key rsa.PrivateKey
140
141	ecdsaP224Key ecdsa.PrivateKey
142	ecdsaP256Key ecdsa.PrivateKey
143	ecdsaP384Key ecdsa.PrivateKey
144	ecdsaP521Key ecdsa.PrivateKey
145
146	ed25519Key ed25519.PrivateKey
147
148	channelIDKey ecdsa.PrivateKey
149)
150
151var channelIDKeyPath string
152
153func initKeys() {
154	// Since key generation is not particularly cheap (especially RSA), and the
155	// runner is intended to run on systems which may be resouece constrained,
156	// we load keys from disk instead of dynamically generating them. We treat
157	// key files the same as dynamically generated certificates, writing them
158	// out to temporary files before passing them to the shim.
159
160	for _, k := range []struct {
161		pemBytes []byte
162		key      *rsa.PrivateKey
163	}{
164		{rsa1024KeyPEM, &rsa1024Key},
165		{rsa2048KeyPEM, &rsa2048Key},
166	} {
167		key, err := loadPEMKey(k.pemBytes)
168		if err != nil {
169			panic(fmt.Sprintf("failed to load RSA test key: %s", err))
170		}
171		*k.key = *(key.(*rsa.PrivateKey))
172	}
173
174	for _, k := range []struct {
175		pemBytes []byte
176		key      *ecdsa.PrivateKey
177	}{
178		{ecdsaP224KeyPEM, &ecdsaP224Key},
179		{ecdsaP256KeyPEM, &ecdsaP256Key},
180		{ecdsaP384KeyPEM, &ecdsaP384Key},
181		{ecdsaP521KeyPEM, &ecdsaP521Key},
182		{channelIDKeyPEM, &channelIDKey},
183	} {
184		key, err := loadPEMKey(k.pemBytes)
185		if err != nil {
186			panic(fmt.Sprintf("failed to load ECDSA test key: %s", err))
187		}
188		*k.key = *(key.(*ecdsa.PrivateKey))
189	}
190
191	k, err := loadPEMKey(ed25519KeyPEM)
192	if err != nil {
193		panic(fmt.Sprintf("failed to load Ed25519 test key: %s", err))
194	}
195	ed25519Key = k.(ed25519.PrivateKey)
196
197	channelIDKeyPath = writeTempKeyFile(&channelIDKey)
198}
199
200var channelIDBytes []byte
201
202var testOCSPResponse = []byte{1, 2, 3, 4}
203var testOCSPResponse2 = []byte{5, 6, 7, 8}
204var testSCTList = []byte{0, 6, 0, 4, 5, 6, 7, 8}
205var testSCTList2 = []byte{0, 6, 0, 4, 1, 2, 3, 4}
206
207var testOCSPExtension = append([]byte{byte(extensionStatusRequest) >> 8, byte(extensionStatusRequest), 0, 8, statusTypeOCSP, 0, 0, 4}, testOCSPResponse...)
208var testSCTExtension = append([]byte{byte(extensionSignedCertificateTimestamp) >> 8, byte(extensionSignedCertificateTimestamp), 0, byte(len(testSCTList))}, testSCTList...)
209
210var (
211	rsaCertificate       Credential
212	rsaChainCertificate  Credential
213	rsa1024Certificate   Credential
214	ecdsaP224Certificate Credential
215	ecdsaP256Certificate Credential
216	ecdsaP384Certificate Credential
217	ecdsaP521Certificate Credential
218	ed25519Certificate   Credential
219	garbageCertificate   Credential
220)
221
222func initCertificates() {
223	for _, def := range []struct {
224		key crypto.Signer
225		out *Credential
226	}{
227		{&rsa1024Key, &rsa1024Certificate},
228		{&rsa2048Key, &rsaCertificate},
229		{&ecdsaP224Key, &ecdsaP224Certificate},
230		{&ecdsaP256Key, &ecdsaP256Certificate},
231		{&ecdsaP384Key, &ecdsaP384Certificate},
232		{&ecdsaP521Key, &ecdsaP521Certificate},
233		{ed25519Key, &ed25519Certificate},
234	} {
235		*def.out = generateSingleCertChain(nil, def.key)
236	}
237
238	channelIDBytes = make([]byte, 64)
239	writeIntPadded(channelIDBytes[:32], channelIDKey.X)
240	writeIntPadded(channelIDBytes[32:], channelIDKey.Y)
241
242	garbageCertificate.Certificate = [][]byte{[]byte("GARBAGE")}
243	garbageCertificate.PrivateKey = rsaCertificate.PrivateKey
244
245	// Build a basic three cert chain for testing chain specific things.
246	rootTmpl := *baseCertTemplate
247	rootTmpl.Subject.CommonName = "test root"
248	rootCert := generateTestCert(&rootTmpl, nil, &rsa2048Key)
249	intermediateTmpl := *baseCertTemplate
250	intermediateTmpl.Subject.CommonName = "test inter"
251	intermediateCert := generateTestCert(&intermediateTmpl, rootCert, &rsa2048Key)
252	leafTmpl := *baseCertTemplate
253	leafTmpl.IsCA, leafTmpl.BasicConstraintsValid = false, false
254	leafCert := generateTestCert(nil, intermediateCert, &rsa2048Key)
255
256	keyPath := writeTempKeyFile(&rsa2048Key)
257	rootCertPath, chainPath := writeTempCertFile([]*x509.Certificate{rootCert}), writeTempCertFile([]*x509.Certificate{leafCert, intermediateCert})
258
259	rsaChainCertificate = Credential{
260		Certificate: [][]byte{leafCert.Raw, intermediateCert.Raw},
261		PrivateKey:  &rsa2048Key,
262		Leaf:        leafCert,
263		ChainPath:   chainPath,
264		KeyPath:     keyPath,
265		RootPath:    rootCertPath,
266	}
267}
268
269func flagInts(flagName string, vals []int) []string {
270	ret := make([]string, 0, 2*len(vals))
271	for _, val := range vals {
272		ret = append(ret, flagName, strconv.Itoa(val))
273	}
274	return ret
275}
276
277func base64FlagValue(in []byte) string {
278	return base64.StdEncoding.EncodeToString(in)
279}
280
281func useDebugger() bool {
282	return *useGDB || *useLLDB || *useRR || *waitForDebugger
283}
284
285// delegatedCredentialConfig specifies the shape of a delegated credential, not
286// including the keys themselves.
287type delegatedCredentialConfig struct {
288	// lifetime is the amount of time, from the notBefore of the parent
289	// certificate, that the delegated credential is valid for. If zero, then 24
290	// hours is assumed.
291	lifetime time.Duration
292	// dcAlgo is the signature scheme that should be used with this delegated
293	// credential. If zero, ECDSA with P-256 is assumed.
294	dcAlgo signatureAlgorithm
295	// algo is the signature algorithm that the delegated credential itself is
296	// signed with. Cannot be zero.
297	algo signatureAlgorithm
298}
299
300func loadPEMKey(pemBytes []byte) (crypto.PrivateKey, error) {
301	block, _ := pem.Decode(pemBytes)
302	if block == nil {
303		return nil, fmt.Errorf("no PEM block found")
304	}
305
306	if block.Type != "PRIVATE KEY" {
307		return nil, fmt.Errorf("unexpected PEM type (expected \"PRIVATE KEY\"): %s", block.Type)
308	}
309
310	k, err := x509.ParsePKCS8PrivateKey(block.Bytes)
311	if err != nil {
312		return nil, fmt.Errorf("failed to parse PKCS#8 key: %s", err)
313	}
314
315	return k, nil
316}
317
318func createDelegatedCredential(parent *Credential, config delegatedCredentialConfig) *Credential {
319	if parent.Type != CredentialTypeX509 {
320		panic("delegated credentials must be issued by X.509 credentials")
321	}
322
323	dcAlgo := config.dcAlgo
324	if dcAlgo == 0 {
325		dcAlgo = signatureECDSAWithP256AndSHA256
326	}
327
328	var dcPriv crypto.Signer
329	switch dcAlgo {
330	case signatureRSAPKCS1WithMD5, signatureRSAPKCS1WithSHA1, signatureRSAPKCS1WithSHA256, signatureRSAPKCS1WithSHA384, signatureRSAPKCS1WithSHA512, signatureRSAPSSWithSHA256, signatureRSAPSSWithSHA384, signatureRSAPSSWithSHA512:
331		dcPriv = &rsa2048Key
332
333	case signatureECDSAWithSHA1, signatureECDSAWithP256AndSHA256, signatureECDSAWithP384AndSHA384, signatureECDSAWithP521AndSHA512:
334		var curve elliptic.Curve
335		switch dcAlgo {
336		case signatureECDSAWithSHA1, signatureECDSAWithP256AndSHA256:
337			curve = elliptic.P256()
338		case signatureECDSAWithP384AndSHA384:
339			curve = elliptic.P384()
340		case signatureECDSAWithP521AndSHA512:
341			curve = elliptic.P521()
342		default:
343			panic("internal error")
344		}
345
346		priv, err := ecdsa.GenerateKey(curve, rand.Reader)
347		if err != nil {
348			panic(err)
349		}
350		dcPriv = priv
351
352	default:
353		panic(fmt.Errorf("unsupported DC signature algorithm: %x", dcAlgo))
354	}
355
356	lifetime := config.lifetime
357	if lifetime == 0 {
358		lifetime = 24 * time.Hour
359	}
360	lifetimeSecs := int64(lifetime.Seconds())
361	if lifetimeSecs < 0 || lifetimeSecs > 1<<32 {
362		panic(fmt.Errorf("lifetime %s is too long to be expressed", lifetime))
363	}
364
365	// https://www.rfc-editor.org/rfc/rfc9345.html#section-4
366	dc := cryptobyte.NewBuilder(nil)
367	dc.AddUint32(uint32(lifetimeSecs))
368	dc.AddUint16(uint16(dcAlgo))
369
370	pubBytes, err := x509.MarshalPKIXPublicKey(dcPriv.Public())
371	if err != nil {
372		panic(err)
373	}
374	addUint24LengthPrefixedBytes(dc, pubBytes)
375
376	var dummyConfig Config
377	parentSignature, err := signMessage(VersionTLS13, parent.PrivateKey, &dummyConfig, config.algo, delegatedCredentialSignedMessage(dc.BytesOrPanic(), config.algo, parent.Leaf.Raw))
378	if err != nil {
379		panic(err)
380	}
381
382	dc.AddUint16(uint16(config.algo))
383	addUint16LengthPrefixedBytes(dc, parentSignature)
384
385	dcCred := *parent
386	dcCred.Type = CredentialTypeDelegated
387	dcCred.DelegatedCredential = dc.BytesOrPanic()
388	dcCred.PrivateKey = dcPriv
389	dcCred.KeyPath = writeTempKeyFile(dcPriv)
390	return &dcCred
391}
392
393// recordVersionToWire maps a record-layer protocol version to its wire
394// representation.
395func recordVersionToWire(vers uint16, protocol protocol) uint16 {
396	if protocol == dtls {
397		switch vers {
398		case VersionTLS12:
399			return VersionDTLS12
400		case VersionTLS10:
401			return VersionDTLS10
402		}
403	} else {
404		switch vers {
405		case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12:
406			return vers
407		}
408	}
409
410	panic("unknown version")
411}
412
413// encodeDERValues encodes a series of bytestrings in comma-separated-hex form.
414func encodeDERValues(values [][]byte) string {
415	var ret string
416	for i, v := range values {
417		if i > 0 {
418			ret += ","
419		}
420		ret += hex.EncodeToString(v)
421	}
422
423	return ret
424}
425
426func decodeHexOrPanic(in string) []byte {
427	ret, err := hex.DecodeString(in)
428	if err != nil {
429		panic(err)
430	}
431	return ret
432}
433
434type testType int
435
436const (
437	clientTest testType = iota
438	serverTest
439)
440
441type protocol int
442
443const (
444	tls protocol = iota
445	dtls
446	quic
447)
448
449func (p protocol) String() string {
450	switch p {
451	case tls:
452		return "TLS"
453	case dtls:
454		return "DTLS"
455	case quic:
456		return "QUIC"
457	}
458	return "unknown protocol"
459}
460
461const (
462	alpn = 1
463	npn  = 2
464)
465
466// connectionExpectations contains connection-level test expectations to check
467// on the runner side.
468type connectionExpectations struct {
469	// version, if non-zero, specifies the TLS version that must be negotiated.
470	version uint16
471	// cipher, if non-zero, specifies the TLS cipher suite that should be
472	// negotiated.
473	cipher uint16
474	// channelID controls whether the connection should have negotiated a
475	// Channel ID with channelIDKey.
476	channelID bool
477	// nextProto controls whether the connection should negotiate a next
478	// protocol via NPN or ALPN.
479	nextProto string
480	// noNextProto, if true, means that no next protocol should be negotiated.
481	noNextProto bool
482	// nextProtoType, if non-zero, is the next protocol negotiation mechanism.
483	nextProtoType int
484	// srtpProtectionProfile is the DTLS-SRTP profile that should be negotiated.
485	// If zero, none should be negotiated.
486	srtpProtectionProfile uint16
487	// peerSignatureAlgorithm, if not zero, is the signature algorithm that the
488	// peer should have used in the handshake.
489	peerSignatureAlgorithm signatureAlgorithm
490	// curveID, if not zero, is the curve that the handshake should have used.
491	curveID CurveID
492	// peerCertificate, if not nil, is the credential the peer is expected to
493	// send.
494	peerCertificate *Credential
495	// quicTransportParams contains the QUIC transport parameters that are to be
496	// sent by the peer using codepoint 57.
497	quicTransportParams []byte
498	// quicTransportParamsLegacy contains the QUIC transport parameters that are
499	// to be sent by the peer using legacy codepoint 0xffa5.
500	quicTransportParamsLegacy []byte
501	// peerApplicationSettings are the expected application settings for the
502	// connection. If nil, no application settings are expected.
503	peerApplicationSettings []byte
504	// peerApplicationSettingsOld are the expected application settings for
505	// the connection that are to be sent by the peer using old codepoint.
506	// If nil, no application settings are expected.
507	peerApplicationSettingsOld []byte
508	// echAccepted is whether ECH should have been accepted on this connection.
509	echAccepted bool
510}
511
512type testCase struct {
513	testType      testType
514	protocol      protocol
515	name          string
516	config        Config
517	shouldFail    bool
518	expectedError string
519	// expectedLocalError, if not empty, contains a substring that must be
520	// found in the local error.
521	expectedLocalError string
522	// expectations contains test expectations for the initial
523	// connection.
524	expectations connectionExpectations
525	// resumeExpectations, if non-nil, contains test expectations for the
526	// resumption connection. If nil, |expectations| is used.
527	resumeExpectations *connectionExpectations
528	// messageLen is the length, in bytes, of the test message that will be
529	// sent.
530	messageLen int
531	// messageCount is the number of test messages that will be sent.
532	messageCount int
533	// resumeSession controls whether a second connection should be tested
534	// which attempts to resume the first session.
535	resumeSession bool
536	// resumeRenewedSession controls whether a third connection should be
537	// tested which attempts to resume the second connection's session.
538	resumeRenewedSession bool
539	// expectResumeRejected, if true, specifies that the attempted
540	// resumption must be rejected by the client. This is only valid for a
541	// serverTest.
542	expectResumeRejected bool
543	// resumeConfig, if not nil, points to a Config to be used on
544	// resumption. Unless newSessionsOnResume is set,
545	// SessionTicketKey, ServerSessionCache, and
546	// ClientSessionCache are copied from the initial connection's
547	// config. If nil, the initial connection's config is used.
548	resumeConfig *Config
549	// newSessionsOnResume, if true, will cause resumeConfig to
550	// use a different session resumption context.
551	newSessionsOnResume bool
552	// noSessionCache, if true, will cause the server to run without a
553	// session cache.
554	noSessionCache bool
555	// sendPrefix sends a prefix on the socket before actually performing a
556	// handshake.
557	sendPrefix string
558	// shimWritesFirst controls whether the shim sends an initial "hello"
559	// message before doing a roundtrip with the runner.
560	shimWritesFirst bool
561	// readWithUnfinishedWrite behaves like shimWritesFirst, but the shim
562	// does not complete the write until responding to the first runner
563	// message.
564	readWithUnfinishedWrite bool
565	// shimShutsDown, if true, runs a test where the shim shuts down the
566	// connection immediately after the handshake rather than echoing
567	// messages from the runner. The runner will default to not sending
568	// application data.
569	shimShutsDown bool
570	// renegotiate indicates the number of times the connection should be
571	// renegotiated during the exchange.
572	renegotiate int
573	// sendHalfHelloRequest, if true, causes the server to send half a
574	// HelloRequest when the handshake completes.
575	sendHalfHelloRequest bool
576	// renegotiateCiphers is a list of ciphersuite ids that will be
577	// switched in just before renegotiation.
578	renegotiateCiphers []uint16
579	// replayWrites, if true, configures the underlying transport
580	// to replay every write it makes in DTLS tests.
581	replayWrites bool
582	// damageFirstWrite, if true, configures the underlying transport to
583	// damage the final byte of the first application data write.
584	damageFirstWrite bool
585	// exportKeyingMaterial, if non-zero, configures the test to exchange
586	// keying material and verify they match.
587	exportKeyingMaterial int
588	exportLabel          string
589	exportContext        string
590	useExportContext     bool
591	// flags, if not empty, contains a list of command-line flags that will
592	// be passed to the shim program.
593	flags []string
594	// testTLSUnique, if true, causes the shim to send the tls-unique value
595	// which will be compared against the expected value.
596	testTLSUnique bool
597	// sendEmptyRecords is the number of consecutive empty records to send
598	// before each test message.
599	sendEmptyRecords int
600	// sendWarningAlerts is the number of consecutive warning alerts to send
601	// before each test message.
602	sendWarningAlerts int
603	// sendUserCanceledAlerts is the number of consecutive user_canceled alerts to
604	// send before each test message.
605	sendUserCanceledAlerts int
606	// sendBogusAlertType, if true, causes a bogus alert of invalid type to
607	// be sent before each test message.
608	sendBogusAlertType bool
609	// sendKeyUpdates is the number of consecutive key updates to send
610	// before and after the test message.
611	sendKeyUpdates int
612	// keyUpdateRequest is the KeyUpdateRequest value to send in KeyUpdate messages.
613	keyUpdateRequest byte
614	// expectUnsolicitedKeyUpdate makes the test expect a one or more KeyUpdate
615	// messages while reading data from the shim. Don't use this in combination
616	// with any of the fields that send a KeyUpdate otherwise any received
617	// KeyUpdate might not be as unsolicited as expected.
618	expectUnsolicitedKeyUpdate bool
619	// expectMessageDropped, if true, means the test message is expected to
620	// be dropped by the client rather than echoed back.
621	expectMessageDropped bool
622	// shimPrefix is the prefix that the shim will send to the server.
623	shimPrefix string
624	// resumeShimPrefix is the prefix that the shim will send to the server on a
625	// resumption.
626	resumeShimPrefix string
627	// exportTrafficSecrets, if true, configures the test to export the TLS 1.3
628	// traffic secrets and confirms that they match.
629	exportTrafficSecrets bool
630	// skipTransportParamsConfig, if true, will skip automatic configuration of
631	// sending QUIC transport parameters when protocol == quic.
632	skipTransportParamsConfig bool
633	// skipQUICALPNConfig, if true, will skip automatic configuration of
634	// sending a fake ALPN when protocol == quic.
635	skipQUICALPNConfig bool
636	// earlyData, if true, configures default settings for an early data test.
637	// expectEarlyDataRejected controls whether the test is for early data
638	// accept or reject. In a client test, the shim will be configured to send
639	// an initial write in early data which, on accept, the runner will enforce.
640	// In a server test, the runner will send some default message in early
641	// data, which the shim is expected to echo in half-RTT.
642	earlyData bool
643	// expectEarlyDataRejected, if earlyData is true, is whether early data is
644	// expected to be rejected. In a client test, this controls whether the shim
645	// should retry for early rejection. In a server test, this is whether the
646	// test expects the shim to reject early data.
647	expectEarlyDataRejected bool
648	// skipSplitHandshake, if true, will skip the generation of a split
649	// handshake copy of the test.
650	skipSplitHandshake bool
651	// skipHints, if true, will skip the generation of a handshake hints copy of
652	// the test.
653	skipHints bool
654	// skipVersionNameCheck, if true, will skip the consistency check between
655	// test name and the versions.
656	skipVersionNameCheck bool
657	// shimCertificate, if not nil, is the default credential which should be
658	// configured at the shim. If set, it must be an X.509 credential.
659	shimCertificate *Credential
660	// handshakerCertificate, if not nil, overrides the default credential which
661	// on the handshaker.
662	handshakerCertificate *Credential
663	// shimCredentials is a list of credentials which should be configured at
664	// the shim. It differs from shimCertificate only in whether the old or
665	// new APIs are used.
666	shimCredentials []*Credential
667}
668
669var testCases []testCase
670
671func appendTranscript(path string, data []byte) error {
672	if len(data) == 0 {
673		return nil
674	}
675
676	settings, err := os.ReadFile(path)
677	if err != nil {
678		if !os.IsNotExist(err) {
679			return err
680		}
681		// If the shim aborted before writing a file, use a default
682		// settings block, so the transcript is still somewhat valid.
683		settings = []byte{0, 0} // kDataTag
684	}
685
686	settings = append(settings, data...)
687	return os.WriteFile(path, settings, 0644)
688}
689
690// A timeoutConn implements an idle timeout on each Read and Write operation.
691type timeoutConn struct {
692	net.Conn
693	timeout time.Duration
694}
695
696func (t *timeoutConn) Read(b []byte) (int, error) {
697	if !*useGDB {
698		if err := t.SetReadDeadline(time.Now().Add(t.timeout)); err != nil {
699			return 0, err
700		}
701	}
702	return t.Conn.Read(b)
703}
704
705func (t *timeoutConn) Write(b []byte) (int, error) {
706	if !*useGDB {
707		if err := t.SetWriteDeadline(time.Now().Add(t.timeout)); err != nil {
708			return 0, err
709		}
710	}
711	return t.Conn.Write(b)
712}
713
714func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool, transcripts *[][]byte, num int) error {
715	if !test.noSessionCache {
716		if config.ClientSessionCache == nil {
717			config.ClientSessionCache = NewLRUClientSessionCache(1)
718		}
719		if config.ServerSessionCache == nil {
720			config.ServerSessionCache = NewLRUServerSessionCache(1)
721		}
722	}
723	if test.testType != clientTest {
724		// Supply a ServerName to ensure a constant session cache key,
725		// rather than falling back to net.Conn.RemoteAddr.
726		if len(config.ServerName) == 0 {
727			config.ServerName = "test"
728		}
729	}
730
731	if *fuzzer {
732		config.Bugs.NullAllCiphers = true
733	}
734	if *deterministic {
735		config.Time = func() time.Time { return time.Unix(1234, 1234) }
736	}
737
738	if !useDebugger() {
739		conn = &timeoutConn{conn, *idleTimeout}
740	}
741
742	if test.protocol == dtls {
743		config.Bugs.PacketAdaptor = newPacketAdaptor(conn)
744		conn = config.Bugs.PacketAdaptor
745	}
746
747	if *flagDebug || len(*transcriptDir) != 0 {
748		local, peer := "client", "server"
749		if test.testType == clientTest {
750			local, peer = peer, local
751		}
752		connDebug := &recordingConn{
753			Conn:       conn,
754			isDatagram: test.protocol == dtls,
755			local:      local,
756			peer:       peer,
757		}
758		conn = connDebug
759		if *flagDebug {
760			defer connDebug.WriteTo(os.Stdout)
761		}
762		if len(*transcriptDir) != 0 {
763			defer func() {
764				if num == len(*transcripts) {
765					*transcripts = append(*transcripts, connDebug.Transcript())
766				} else {
767					panic("transcripts are out of sync")
768				}
769			}()
770
771			// Record ClientHellos for the decode_client_hello_inner fuzzer.
772			var clientHelloCount int
773			config.Bugs.RecordClientHelloInner = func(encodedInner, outer []byte) error {
774				name := fmt.Sprintf("%s-%d-%d", test.name, num, clientHelloCount)
775				clientHelloCount++
776				dir := filepath.Join(*transcriptDir, "decode_client_hello_inner")
777				if err := os.MkdirAll(dir, 0755); err != nil {
778					return err
779				}
780				bb := cryptobyte.NewBuilder(nil)
781				addUint24LengthPrefixedBytes(bb, encodedInner)
782				bb.AddBytes(outer)
783				return os.WriteFile(filepath.Join(dir, name), bb.BytesOrPanic(), 0644)
784			}
785		}
786
787		if config.Bugs.PacketAdaptor != nil {
788			config.Bugs.PacketAdaptor.debug = connDebug
789		}
790	}
791	if test.protocol == quic {
792		config.Bugs.MockQUICTransport = newMockQUICTransport(conn)
793		// The MockQUICTransport will panic if Read or Write is
794		// called. When a MockQUICTransport is set, separate
795		// methods should be used to actually read and write
796		// records. By setting the conn to it here, it ensures
797		// Read or Write aren't accidentally used instead of the
798		// methods provided by MockQUICTransport.
799		conn = config.Bugs.MockQUICTransport
800	}
801
802	if test.replayWrites {
803		conn = newReplayAdaptor(conn)
804	}
805
806	var connDamage *damageAdaptor
807	if test.damageFirstWrite {
808		connDamage = newDamageAdaptor(conn)
809		conn = connDamage
810	}
811
812	if test.sendPrefix != "" {
813		if _, err := conn.Write([]byte(test.sendPrefix)); err != nil {
814			return err
815		}
816	}
817
818	var tlsConn *Conn
819	if test.testType == clientTest {
820		if test.protocol == dtls {
821			tlsConn = DTLSServer(conn, config)
822		} else {
823			tlsConn = Server(conn, config)
824		}
825	} else {
826		config.InsecureSkipVerify = true
827		if test.protocol == dtls {
828			tlsConn = DTLSClient(conn, config)
829		} else {
830			tlsConn = Client(conn, config)
831		}
832	}
833	defer tlsConn.Close()
834
835	if err := tlsConn.Handshake(); err != nil {
836		return err
837	}
838
839	expectations := &test.expectations
840	if isResume && test.resumeExpectations != nil {
841		expectations = test.resumeExpectations
842	}
843	connState := tlsConn.ConnectionState()
844	if vers := connState.Version; expectations.version != 0 && vers != expectations.version {
845		return fmt.Errorf("got version %x, expected %x", vers, expectations.version)
846	}
847
848	if cipher := connState.CipherSuite; expectations.cipher != 0 && cipher != expectations.cipher {
849		return fmt.Errorf("got cipher %x, expected %x", cipher, expectations.cipher)
850	}
851	if didResume := connState.DidResume; isResume && didResume == test.expectResumeRejected {
852		return fmt.Errorf("didResume is %t, but we expected the opposite", didResume)
853	}
854
855	if expectations.channelID {
856		channelID := connState.ChannelID
857		if channelID == nil {
858			return fmt.Errorf("no channel ID negotiated")
859		}
860		if channelID.Curve != channelIDKey.Curve ||
861			channelIDKey.X.Cmp(channelIDKey.X) != 0 ||
862			channelIDKey.Y.Cmp(channelIDKey.Y) != 0 {
863			return fmt.Errorf("incorrect channel ID")
864		}
865	} else if connState.ChannelID != nil {
866		return fmt.Errorf("channel ID unexpectedly negotiated")
867	}
868
869	if expected := expectations.nextProto; expected != "" {
870		if actual := connState.NegotiatedProtocol; actual != expected {
871			return fmt.Errorf("next proto mismatch: got %s, wanted %s", actual, expected)
872		}
873	}
874
875	if expectations.noNextProto {
876		if actual := connState.NegotiatedProtocol; actual != "" {
877			return fmt.Errorf("got unexpected next proto %s", actual)
878		}
879	}
880
881	if expectations.nextProtoType != 0 {
882		if (expectations.nextProtoType == alpn) != connState.NegotiatedProtocolFromALPN {
883			return fmt.Errorf("next proto type mismatch")
884		}
885	}
886
887	if expectations.peerApplicationSettings != nil {
888		if !connState.HasApplicationSettings {
889			return errors.New("application settings should have been negotiated")
890		}
891		if !bytes.Equal(connState.PeerApplicationSettings, expectations.peerApplicationSettings) {
892			return fmt.Errorf("peer application settings mismatch: got %q, wanted %q", connState.PeerApplicationSettings, expectations.peerApplicationSettings)
893		}
894	} else if connState.HasApplicationSettings {
895		return errors.New("application settings unexpectedly negotiated")
896	}
897
898	if expectations.peerApplicationSettingsOld != nil {
899		if !connState.HasApplicationSettingsOld {
900			return errors.New("old application settings should have been negotiated")
901		}
902		if !bytes.Equal(connState.PeerApplicationSettingsOld, expectations.peerApplicationSettingsOld) {
903			return fmt.Errorf("old peer application settings mismatch: got %q, wanted %q", connState.PeerApplicationSettingsOld, expectations.peerApplicationSettingsOld)
904		}
905	} else if connState.HasApplicationSettingsOld {
906		return errors.New("old application settings unexpectedly negotiated")
907	}
908
909	if p := connState.SRTPProtectionProfile; p != expectations.srtpProtectionProfile {
910		return fmt.Errorf("SRTP profile mismatch: got %d, wanted %d", p, expectations.srtpProtectionProfile)
911	}
912
913	if expected := expectations.peerSignatureAlgorithm; expected != 0 && expected != connState.PeerSignatureAlgorithm {
914		return fmt.Errorf("expected peer to use signature algorithm %04x, but got %04x", expected, connState.PeerSignatureAlgorithm)
915	}
916
917	if expected := expectations.curveID; expected != 0 && expected != connState.CurveID {
918		return fmt.Errorf("expected peer to use curve %04x, but got %04x", expected, connState.CurveID)
919	}
920
921	if expected := expectations.peerCertificate; expected != nil {
922		if len(connState.PeerCertificates) != len(expected.Certificate) {
923			return fmt.Errorf("expected peer to send %d certificates, but got %d", len(connState.PeerCertificates), len(expected.Certificate))
924		}
925		for i, cert := range connState.PeerCertificates {
926			if !bytes.Equal(cert.Raw, expected.Certificate[i]) {
927				return fmt.Errorf("peer certificate %d did not match", i+1)
928			}
929		}
930
931		if !bytes.Equal(connState.OCSPResponse, expected.OCSPStaple) {
932			return fmt.Errorf("peer OCSP response did not match")
933		}
934
935		if !bytes.Equal(connState.SCTList, expected.SignedCertificateTimestampList) {
936			return fmt.Errorf("peer SCT list did not match")
937		}
938
939		if expected.Type == CredentialTypeDelegated {
940			if connState.PeerDelegatedCredential == nil {
941				return fmt.Errorf("peer unexpectedly did not use delegated credentials")
942			}
943			if !bytes.Equal(expected.DelegatedCredential, connState.PeerDelegatedCredential) {
944				return fmt.Errorf("peer delegated credential did not match")
945			}
946		} else if connState.PeerDelegatedCredential != nil {
947			return fmt.Errorf("peer unexpectedly used delegated credentials")
948		}
949	}
950
951	if len(expectations.quicTransportParams) > 0 {
952		if !bytes.Equal(expectations.quicTransportParams, connState.QUICTransportParams) {
953			return errors.New("Peer did not send expected QUIC transport params")
954		}
955	}
956
957	if len(expectations.quicTransportParamsLegacy) > 0 {
958		if !bytes.Equal(expectations.quicTransportParamsLegacy, connState.QUICTransportParamsLegacy) {
959			return errors.New("Peer did not send expected legacy QUIC transport params")
960		}
961	}
962
963	if expectations.echAccepted {
964		if !connState.ECHAccepted {
965			return errors.New("tls: server did not accept ECH")
966		}
967	} else {
968		if connState.ECHAccepted {
969			return errors.New("tls: server unexpectedly accepted ECH")
970		}
971	}
972
973	if test.exportKeyingMaterial > 0 {
974		actual := make([]byte, test.exportKeyingMaterial)
975		if _, err := io.ReadFull(tlsConn, actual); err != nil {
976			return err
977		}
978		expected, err := tlsConn.ExportKeyingMaterial(test.exportKeyingMaterial, []byte(test.exportLabel), []byte(test.exportContext), test.useExportContext)
979		if err != nil {
980			return err
981		}
982		if !bytes.Equal(actual, expected) {
983			return fmt.Errorf("keying material mismatch; got %x, wanted %x", actual, expected)
984		}
985	}
986
987	if test.exportTrafficSecrets {
988		secretLenBytes := make([]byte, 2)
989		if _, err := io.ReadFull(tlsConn, secretLenBytes); err != nil {
990			return err
991		}
992		secretLen := binary.LittleEndian.Uint16(secretLenBytes)
993
994		theirReadSecret := make([]byte, secretLen)
995		theirWriteSecret := make([]byte, secretLen)
996		if _, err := io.ReadFull(tlsConn, theirReadSecret); err != nil {
997			return err
998		}
999		if _, err := io.ReadFull(tlsConn, theirWriteSecret); err != nil {
1000			return err
1001		}
1002
1003		myReadSecret := tlsConn.in.trafficSecret
1004		myWriteSecret := tlsConn.out.trafficSecret
1005		if !bytes.Equal(myWriteSecret, theirReadSecret) {
1006			return fmt.Errorf("read traffic-secret mismatch; got %x, wanted %x", theirReadSecret, myWriteSecret)
1007		}
1008		if !bytes.Equal(myReadSecret, theirWriteSecret) {
1009			return fmt.Errorf("write traffic-secret mismatch; got %x, wanted %x", theirWriteSecret, myReadSecret)
1010		}
1011	}
1012
1013	if test.testTLSUnique {
1014		var peersValue [12]byte
1015		if _, err := io.ReadFull(tlsConn, peersValue[:]); err != nil {
1016			return err
1017		}
1018		expected := tlsConn.ConnectionState().TLSUnique
1019		if !bytes.Equal(peersValue[:], expected) {
1020			return fmt.Errorf("tls-unique mismatch: peer sent %x, but %x was expected", peersValue[:], expected)
1021		}
1022	}
1023
1024	if test.sendHalfHelloRequest {
1025		tlsConn.SendHalfHelloRequest()
1026	}
1027
1028	shimPrefix := test.shimPrefix
1029	if isResume {
1030		shimPrefix = test.resumeShimPrefix
1031	}
1032	if test.shimWritesFirst || test.readWithUnfinishedWrite {
1033		shimPrefix = shimInitialWrite
1034	}
1035	if test.renegotiate > 0 {
1036		// If readWithUnfinishedWrite is set, the shim prefix will be
1037		// available later.
1038		if shimPrefix != "" && !test.readWithUnfinishedWrite {
1039			var buf = make([]byte, len(shimPrefix))
1040			_, err := io.ReadFull(tlsConn, buf)
1041			if err != nil {
1042				return err
1043			}
1044			if string(buf) != shimPrefix {
1045				return fmt.Errorf("bad initial message %v vs %v", string(buf), shimPrefix)
1046			}
1047			shimPrefix = ""
1048		}
1049
1050		if test.renegotiateCiphers != nil {
1051			config.CipherSuites = test.renegotiateCiphers
1052		}
1053		for i := 0; i < test.renegotiate; i++ {
1054			if err := tlsConn.Renegotiate(); err != nil {
1055				return err
1056			}
1057		}
1058	} else if test.renegotiateCiphers != nil {
1059		panic("renegotiateCiphers without renegotiate")
1060	}
1061
1062	if test.damageFirstWrite {
1063		connDamage.setDamage(true)
1064		tlsConn.Write([]byte("DAMAGED WRITE"))
1065		connDamage.setDamage(false)
1066	}
1067
1068	messageLen := test.messageLen
1069	if messageLen < 0 {
1070		if test.protocol == dtls {
1071			return fmt.Errorf("messageLen < 0 not supported for DTLS tests")
1072		}
1073		// Read until EOF.
1074		_, err := io.Copy(io.Discard, tlsConn)
1075		return err
1076	}
1077	if messageLen == 0 {
1078		messageLen = 32
1079	}
1080
1081	messageCount := test.messageCount
1082	// shimShutsDown sets the default message count to zero.
1083	if messageCount == 0 && !test.shimShutsDown {
1084		messageCount = 1
1085	}
1086
1087	for j := 0; j < messageCount; j++ {
1088		for i := 0; i < test.sendKeyUpdates; i++ {
1089			tlsConn.SendKeyUpdate(test.keyUpdateRequest)
1090		}
1091
1092		for i := 0; i < test.sendEmptyRecords; i++ {
1093			tlsConn.Write(nil)
1094		}
1095
1096		for i := 0; i < test.sendWarningAlerts; i++ {
1097			tlsConn.SendAlert(alertLevelWarning, alertUnexpectedMessage)
1098		}
1099
1100		for i := 0; i < test.sendUserCanceledAlerts; i++ {
1101			tlsConn.SendAlert(alertLevelWarning, alertUserCanceled)
1102		}
1103
1104		if test.sendBogusAlertType {
1105			tlsConn.SendAlert(0x42, alertUnexpectedMessage)
1106		}
1107
1108		testMessage := make([]byte, messageLen)
1109		for i := range testMessage {
1110			testMessage[i] = 0x42 ^ byte(j)
1111		}
1112		tlsConn.Write(testMessage)
1113
1114		// Consume the shim prefix if needed.
1115		if shimPrefix != "" {
1116			var buf = make([]byte, len(shimPrefix))
1117			_, err := io.ReadFull(tlsConn, buf)
1118			if err != nil {
1119				return err
1120			}
1121			if string(buf) != shimPrefix {
1122				return fmt.Errorf("bad initial message %v vs %v", string(buf), shimPrefix)
1123			}
1124			shimPrefix = ""
1125		}
1126
1127		if test.shimShutsDown || test.expectMessageDropped {
1128			// The shim will not respond.
1129			continue
1130		}
1131
1132		// Process the KeyUpdate ACK. However many KeyUpdates the runner
1133		// sends, the shim should respond only once.
1134		if test.sendKeyUpdates > 0 && test.keyUpdateRequest == keyUpdateRequested {
1135			if err := tlsConn.ReadKeyUpdateACK(); err != nil {
1136				return err
1137			}
1138		}
1139
1140		buf := make([]byte, len(testMessage))
1141		if test.protocol == dtls {
1142			bufTmp := make([]byte, len(buf)+1)
1143			n, err := tlsConn.Read(bufTmp)
1144			if err != nil {
1145				return err
1146			}
1147			if config.Bugs.SplitAndPackAppData {
1148				m, err := tlsConn.Read(bufTmp[n:])
1149				if err != nil {
1150					return err
1151				}
1152				n += m
1153			}
1154			if n != len(buf) {
1155				return fmt.Errorf("bad reply; length mismatch (%d vs %d)", n, len(buf))
1156			}
1157			copy(buf, bufTmp)
1158		} else {
1159			_, err := io.ReadFull(tlsConn, buf)
1160			if err != nil {
1161				return err
1162			}
1163		}
1164
1165		for i, v := range buf {
1166			if v != testMessage[i]^0xff {
1167				return fmt.Errorf("bad reply contents at byte %d; got %q and wanted %q", i, buf, testMessage)
1168			}
1169		}
1170
1171		if seen := tlsConn.keyUpdateSeen; seen != test.expectUnsolicitedKeyUpdate {
1172			return fmt.Errorf("keyUpdateSeen (%t) != expectUnsolicitedKeyUpdate", seen)
1173		}
1174	}
1175
1176	return nil
1177}
1178
1179const xtermSize = "140x50"
1180
1181func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
1182	valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full", "--quiet"}
1183	if dbAttach {
1184		valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -geometry "+xtermSize+" -e gdb -nw %f %p")
1185	}
1186	valgrindArgs = append(valgrindArgs, path)
1187	valgrindArgs = append(valgrindArgs, args...)
1188
1189	return exec.Command("valgrind", valgrindArgs...)
1190}
1191
1192func gdbOf(path string, args ...string) *exec.Cmd {
1193	xtermArgs := []string{"-geometry", xtermSize, "-e", "gdb", "--args"}
1194	xtermArgs = append(xtermArgs, path)
1195	xtermArgs = append(xtermArgs, args...)
1196
1197	return exec.Command("xterm", xtermArgs...)
1198}
1199
1200func lldbOf(path string, args ...string) *exec.Cmd {
1201	xtermArgs := []string{"-geometry", xtermSize, "-e", "lldb", "--"}
1202	xtermArgs = append(xtermArgs, path)
1203	xtermArgs = append(xtermArgs, args...)
1204
1205	return exec.Command("xterm", xtermArgs...)
1206}
1207
1208func rrOf(path string, args ...string) *exec.Cmd {
1209	rrArgs := []string{"record", path}
1210	rrArgs = append(rrArgs, args...)
1211	return exec.Command("rr", rrArgs...)
1212}
1213
1214func removeFirstLineIfSuffix(s, suffix string) string {
1215	idx := strings.IndexByte(s, '\n')
1216	if idx < 0 {
1217		return s
1218	}
1219	if strings.HasSuffix(s[:idx], suffix) {
1220		return s[idx+1:]
1221	}
1222	return s
1223}
1224
1225var (
1226	errMoreMallocs   = errors.New("child process did not exhaust all allocation calls")
1227	errUnimplemented = errors.New("child process does not implement needed flags")
1228)
1229
1230type shimProcess struct {
1231	cmd *exec.Cmd
1232	// done is closed when the process has exited. At that point, childErr may be
1233	// read for the result.
1234	done           chan struct{}
1235	childErr       error
1236	listener       *shimListener
1237	stdout, stderr bytes.Buffer
1238}
1239
1240// newShimProcess starts a new shim with the specified executable, flags, and
1241// environment. It internally creates a TCP listener and adds the the -port
1242// flag.
1243func newShimProcess(dispatcher *shimDispatcher, shimPath string, flags []string, env []string) (*shimProcess, error) {
1244	listener, err := dispatcher.NewShim()
1245	if err != nil {
1246		return nil, err
1247	}
1248
1249	shim := &shimProcess{listener: listener}
1250	cmdFlags := []string{
1251		"-port", strconv.Itoa(listener.Port()),
1252		"-shim-id", strconv.FormatUint(listener.ShimID(), 10),
1253	}
1254	if listener.IsIPv6() {
1255		cmdFlags = append(cmdFlags, "-ipv6")
1256	}
1257	cmdFlags = append(cmdFlags, flags...)
1258
1259	if *useValgrind {
1260		shim.cmd = valgrindOf(false, shimPath, cmdFlags...)
1261	} else if *useGDB {
1262		shim.cmd = gdbOf(shimPath, cmdFlags...)
1263	} else if *useLLDB {
1264		shim.cmd = lldbOf(shimPath, cmdFlags...)
1265	} else if *useRR {
1266		shim.cmd = rrOf(shimPath, cmdFlags...)
1267	} else {
1268		shim.cmd = exec.Command(shimPath, cmdFlags...)
1269	}
1270	shim.cmd.Stdin = os.Stdin
1271	shim.cmd.Stdout = &shim.stdout
1272	shim.cmd.Stderr = &shim.stderr
1273	shim.cmd.Env = env
1274
1275	if err := shim.cmd.Start(); err != nil {
1276		shim.listener.Close()
1277		return nil, err
1278	}
1279
1280	shim.done = make(chan struct{})
1281	go func() {
1282		shim.childErr = shim.cmd.Wait()
1283		shim.listener.Close()
1284		close(shim.done)
1285	}()
1286	return shim, nil
1287}
1288
1289// accept returns a new TCP connection with the shim process, or returns an
1290// error on timeout or shim exit.
1291func (s *shimProcess) accept() (net.Conn, error) {
1292	var deadline time.Time
1293	if !useDebugger() {
1294		deadline = time.Now().Add(*idleTimeout)
1295	}
1296	return s.listener.Accept(deadline)
1297}
1298
1299// wait finishes the test and waits for the shim process to exit.
1300func (s *shimProcess) wait() error {
1301	// Close the listener now. This is to avoid hangs if the shim tries to open
1302	// more connections than expected.
1303	s.listener.Close()
1304
1305	if !useDebugger() {
1306		waitTimeout := time.AfterFunc(*idleTimeout, func() {
1307			s.cmd.Process.Kill()
1308		})
1309		defer waitTimeout.Stop()
1310	}
1311
1312	<-s.done
1313	return s.childErr
1314}
1315
1316// close releases resources associated with the shimProcess. This is safe to
1317// call before or after |wait|.
1318func (s *shimProcess) close() {
1319	s.listener.Close()
1320	s.cmd.Process.Kill()
1321}
1322
1323func doExchanges(test *testCase, shim *shimProcess, resumeCount int, transcripts *[][]byte) error {
1324	config := test.config
1325	if *deterministic {
1326		config.Rand = &deterministicRand{}
1327	}
1328
1329	conn, err := shim.accept()
1330	if err != nil {
1331		return err
1332	}
1333	err = doExchange(test, &config, conn, false /* not a resumption */, transcripts, 0)
1334	conn.Close()
1335	if err != nil {
1336		return err
1337	}
1338
1339	nextTicketKey := config.SessionTicketKey
1340	for i := 0; i < resumeCount; i++ {
1341		var resumeConfig Config
1342		if test.resumeConfig != nil {
1343			resumeConfig = *test.resumeConfig
1344			resumeConfig.Rand = config.Rand
1345			if resumeConfig.Credential == nil {
1346				resumeConfig.Credential = config.Credential
1347			}
1348		} else {
1349			resumeConfig = config
1350		}
1351
1352		if test.newSessionsOnResume {
1353			resumeConfig.ClientSessionCache = nil
1354			resumeConfig.ServerSessionCache = nil
1355			if _, err := resumeConfig.rand().Read(resumeConfig.SessionTicketKey[:]); err != nil {
1356				return err
1357			}
1358		} else {
1359			resumeConfig.ClientSessionCache = config.ClientSessionCache
1360			resumeConfig.ServerSessionCache = config.ServerSessionCache
1361			// Rotate the ticket keys between each connection, with each connection
1362			// encrypting with next connection's keys. This ensures that we test
1363			// the renewed sessions.
1364			resumeConfig.SessionTicketKey = nextTicketKey
1365			if _, err := resumeConfig.rand().Read(nextTicketKey[:]); err != nil {
1366				return err
1367			}
1368			resumeConfig.Bugs.EncryptSessionTicketKey = &nextTicketKey
1369		}
1370
1371		var connResume net.Conn
1372		connResume, err = shim.accept()
1373		if err != nil {
1374			return err
1375		}
1376		err = doExchange(test, &resumeConfig, connResume, true /* resumption */, transcripts, i+1)
1377		connResume.Close()
1378		if err != nil {
1379			return err
1380		}
1381	}
1382
1383	return nil
1384}
1385
1386func translateExpectedError(errorStr string) string {
1387	if translated, ok := shimConfig.ErrorMap[errorStr]; ok {
1388		return translated
1389	}
1390
1391	if *looseErrors {
1392		return ""
1393	}
1394
1395	return errorStr
1396}
1397
1398// shimInitialWrite is the data we expect from the shim when the
1399// -shim-writes-first flag is used.
1400const shimInitialWrite = "hello"
1401
1402func appendCredentialFlags(flags []string, cred *Credential, prefix string, newCredential bool) []string {
1403	if newCredential {
1404		switch cred.Type {
1405		case CredentialTypeX509:
1406			flags = append(flags, prefix+"-new-x509-credential")
1407		case CredentialTypeDelegated:
1408			flags = append(flags, prefix+"-new-delegated-credential")
1409		default:
1410			panic(fmt.Errorf("unknown credential type %d", cred.Type))
1411		}
1412	} else if cred.Type != CredentialTypeX509 {
1413		panic("default credential must be X.509")
1414	}
1415
1416	if len(cred.ChainPath) != 0 {
1417		flags = append(flags, prefix+"-cert-file", cred.ChainPath)
1418	}
1419	if len(cred.KeyPath) != 0 {
1420		flags = append(flags, prefix+"-key-file", cred.KeyPath)
1421	}
1422	if len(cred.OCSPStaple) != 0 {
1423		flags = append(flags, prefix+"-ocsp-response", base64FlagValue(cred.OCSPStaple))
1424	}
1425	if len(cred.SignedCertificateTimestampList) != 0 {
1426		flags = append(flags, prefix+"-signed-cert-timestamps", base64FlagValue(cred.SignedCertificateTimestampList))
1427	}
1428	for _, sigAlg := range cred.SignatureAlgorithms {
1429		flags = append(flags, prefix+"-signing-prefs", strconv.Itoa(int(sigAlg)))
1430	}
1431	if len(cred.DelegatedCredential) != 0 {
1432		flags = append(flags, prefix+"-delegated-credential", base64FlagValue(cred.DelegatedCredential))
1433	}
1434	return flags
1435}
1436
1437func runTest(dispatcher *shimDispatcher, statusChan chan statusMsg, test *testCase, shimPath string, mallocNumToFail int64) error {
1438	// Help debugging panics on the Go side.
1439	defer func() {
1440		if r := recover(); r != nil {
1441			fmt.Fprintf(os.Stderr, "Test '%s' panicked.\n", test.name)
1442			panic(r)
1443		}
1444	}()
1445
1446	var flags []string
1447	if len(*shimExtraFlags) > 0 {
1448		flags = strings.Split(*shimExtraFlags, ";")
1449	}
1450	if test.testType == serverTest {
1451		flags = append(flags, "-server")
1452	}
1453
1454	// Configure the default credential.
1455	shimCertificate := test.shimCertificate
1456	if shimCertificate == nil && len(test.shimCredentials) == 0 && test.testType == serverTest && len(test.config.PreSharedKey) == 0 {
1457		shimCertificate = &rsaCertificate
1458	}
1459	if shimCertificate != nil {
1460		var shimPrefix string
1461		if test.handshakerCertificate != nil {
1462			shimPrefix = "-on-shim"
1463		}
1464		flags = appendCredentialFlags(flags, shimCertificate, shimPrefix, false)
1465	}
1466	if test.handshakerCertificate != nil {
1467		flags = appendCredentialFlags(flags, test.handshakerCertificate, "-on-handshaker", false)
1468	}
1469
1470	// Configure any additional credentials.
1471	for _, cred := range test.shimCredentials {
1472		flags = appendCredentialFlags(flags, cred, "", true)
1473	}
1474
1475	if test.protocol == dtls {
1476		flags = append(flags, "-dtls")
1477	} else if test.protocol == quic {
1478		flags = append(flags, "-quic")
1479		if !test.skipTransportParamsConfig {
1480			test.config.QUICTransportParams = []byte{1, 2}
1481			test.config.QUICTransportParamsUseLegacyCodepoint = QUICUseCodepointStandard
1482			if test.resumeConfig != nil {
1483				test.resumeConfig.QUICTransportParams = []byte{1, 2}
1484				test.resumeConfig.QUICTransportParamsUseLegacyCodepoint = QUICUseCodepointStandard
1485			}
1486			test.expectations.quicTransportParams = []byte{3, 4}
1487			if test.resumeExpectations != nil {
1488				test.resumeExpectations.quicTransportParams = []byte{3, 4}
1489			}
1490			useCodepointFlag := "0"
1491			if test.config.QUICTransportParamsUseLegacyCodepoint == QUICUseCodepointLegacy {
1492				useCodepointFlag = "1"
1493			}
1494			flags = append(flags,
1495				"-quic-transport-params",
1496				base64FlagValue([]byte{3, 4}),
1497				"-expect-quic-transport-params",
1498				base64FlagValue([]byte{1, 2}),
1499				"-quic-use-legacy-codepoint", useCodepointFlag)
1500		}
1501		if !test.skipQUICALPNConfig {
1502			flags = append(flags,
1503				[]string{
1504					"-advertise-alpn", "\x03foo",
1505					"-select-alpn", "foo",
1506					"-expect-alpn", "foo",
1507				}...)
1508			test.config.NextProtos = []string{"foo"}
1509			if test.resumeConfig != nil {
1510				test.resumeConfig.NextProtos = []string{"foo"}
1511			}
1512			test.expectations.nextProto = "foo"
1513			test.expectations.nextProtoType = alpn
1514			if test.resumeExpectations != nil {
1515				test.resumeExpectations.nextProto = "foo"
1516				test.resumeExpectations.nextProtoType = alpn
1517			}
1518		}
1519	}
1520
1521	if test.earlyData {
1522		if !test.resumeSession {
1523			panic("earlyData set without resumeSession in " + test.name)
1524		}
1525
1526		resumeConfig := test.resumeConfig
1527		if resumeConfig == nil {
1528			resumeConfig = &test.config
1529		}
1530		if test.expectEarlyDataRejected {
1531			flags = append(flags, "-on-resume-expect-reject-early-data")
1532		} else {
1533			flags = append(flags, "-on-resume-expect-accept-early-data")
1534		}
1535
1536		if test.protocol == quic {
1537			// QUIC requires an early data context string.
1538			flags = append(flags, "-quic-early-data-context", "context")
1539		}
1540
1541		flags = append(flags, "-enable-early-data")
1542		if test.testType == clientTest {
1543			// Configure the runner with default maximum early data.
1544			flags = append(flags, "-expect-ticket-supports-early-data")
1545			if test.config.MaxEarlyDataSize == 0 {
1546				test.config.MaxEarlyDataSize = 16384
1547			}
1548			if resumeConfig.MaxEarlyDataSize == 0 {
1549				resumeConfig.MaxEarlyDataSize = 16384
1550			}
1551
1552			// Configure the shim to send some data in early data.
1553			flags = append(flags, "-on-resume-shim-writes-first")
1554			if resumeConfig.Bugs.ExpectEarlyData == nil {
1555				resumeConfig.Bugs.ExpectEarlyData = [][]byte{[]byte(shimInitialWrite)}
1556			}
1557		} else {
1558			// By default, send some early data and expect half-RTT data response.
1559			if resumeConfig.Bugs.SendEarlyData == nil {
1560				resumeConfig.Bugs.SendEarlyData = [][]byte{{1, 2, 3, 4}}
1561			}
1562			if resumeConfig.Bugs.ExpectHalfRTTData == nil {
1563				resumeConfig.Bugs.ExpectHalfRTTData = [][]byte{{254, 253, 252, 251}}
1564			}
1565			resumeConfig.Bugs.ExpectEarlyDataAccepted = !test.expectEarlyDataRejected
1566		}
1567	}
1568
1569	var resumeCount int
1570	if test.resumeSession {
1571		resumeCount++
1572		if test.resumeRenewedSession {
1573			resumeCount++
1574		}
1575	}
1576
1577	if resumeCount > 0 {
1578		flags = append(flags, "-resume-count", strconv.Itoa(resumeCount))
1579	}
1580
1581	if test.shimWritesFirst {
1582		flags = append(flags, "-shim-writes-first")
1583	}
1584
1585	if test.readWithUnfinishedWrite {
1586		flags = append(flags, "-read-with-unfinished-write")
1587	}
1588
1589	if test.shimShutsDown {
1590		flags = append(flags, "-shim-shuts-down")
1591	}
1592
1593	if test.exportKeyingMaterial > 0 {
1594		flags = append(flags, "-export-keying-material", strconv.Itoa(test.exportKeyingMaterial))
1595		if test.useExportContext {
1596			flags = append(flags, "-use-export-context")
1597		}
1598	}
1599	if test.exportKeyingMaterial > 0 {
1600		flags = append(flags, "-export-label", test.exportLabel)
1601		flags = append(flags, "-export-context", test.exportContext)
1602	}
1603
1604	if test.exportTrafficSecrets {
1605		flags = append(flags, "-export-traffic-secrets")
1606	}
1607
1608	if test.expectResumeRejected {
1609		flags = append(flags, "-expect-session-miss")
1610	}
1611
1612	if test.testTLSUnique {
1613		flags = append(flags, "-tls-unique")
1614	}
1615
1616	if *waitForDebugger {
1617		flags = append(flags, "-wait-for-debugger")
1618	}
1619
1620	var transcriptPrefix string
1621	var transcripts [][]byte
1622	if len(*transcriptDir) != 0 {
1623		protocol := "tls"
1624		if test.protocol == dtls {
1625			protocol = "dtls"
1626		} else if test.protocol == quic {
1627			protocol = "quic"
1628		}
1629
1630		side := "client"
1631		if test.testType == serverTest {
1632			side = "server"
1633		}
1634
1635		dir := filepath.Join(*transcriptDir, protocol, side)
1636		if err := os.MkdirAll(dir, 0755); err != nil {
1637			return err
1638		}
1639		transcriptPrefix = filepath.Join(dir, test.name+"-")
1640		flags = append(flags, "-write-settings", transcriptPrefix)
1641	}
1642
1643	if test.testType == clientTest && test.config.Credential == nil {
1644		test.config.Credential = &rsaCertificate
1645	}
1646	if test.config.Credential != nil {
1647		flags = append(flags, "-trust-cert", test.config.Credential.RootPath)
1648	}
1649
1650	flags = append(flags, test.flags...)
1651
1652	var env []string
1653	if mallocNumToFail >= 0 {
1654		env = os.Environ()
1655		env = append(env, "MALLOC_NUMBER_TO_FAIL="+strconv.FormatInt(mallocNumToFail, 10))
1656		if *mallocTestDebug {
1657			env = append(env, "MALLOC_BREAK_ON_FAIL=1")
1658		}
1659		env = append(env, "_MALLOC_CHECK=1")
1660	}
1661
1662	shim, err := newShimProcess(dispatcher, shimPath, flags, env)
1663	if err != nil {
1664		return err
1665	}
1666	statusChan <- statusMsg{test: test, statusType: statusShimStarted, pid: shim.cmd.Process.Pid}
1667	defer shim.close()
1668
1669	localErr := doExchanges(test, shim, resumeCount, &transcripts)
1670	childErr := shim.wait()
1671
1672	// Now that the shim has exited, all the settings files have been
1673	// written. Append the saved transcripts.
1674	for i, transcript := range transcripts {
1675		if err := appendTranscript(transcriptPrefix+strconv.Itoa(i), transcript); err != nil {
1676			return err
1677		}
1678	}
1679
1680	var isValgrindError, mustFail bool
1681	if exitError, ok := childErr.(*exec.ExitError); ok {
1682		switch exitError.Sys().(syscall.WaitStatus).ExitStatus() {
1683		case 88:
1684			return errMoreMallocs
1685		case 89:
1686			return errUnimplemented
1687		case 90:
1688			mustFail = true
1689		case 99:
1690			isValgrindError = true
1691		}
1692	}
1693
1694	// Account for Windows line endings.
1695	stdout := strings.Replace(shim.stdout.String(), "\r\n", "\n", -1)
1696	stderr := strings.Replace(shim.stderr.String(), "\r\n", "\n", -1)
1697
1698	// Work around an NDK / Android bug. The NDK r16 sometimes generates
1699	// binaries with the DF_1_PIE, which the runtime linker on Android N
1700	// complains about. The next NDK revision should work around this but,
1701	// in the meantime, strip its error out.
1702	//
1703	// https://github.com/android-ndk/ndk/issues/602
1704	// https://android-review.googlesource.com/c/platform/bionic/+/259790
1705	// https://android-review.googlesource.com/c/toolchain/binutils/+/571550
1706	//
1707	// Remove this after switching to the r17 NDK.
1708	stderr = removeFirstLineIfSuffix(stderr, ": unsupported flags DT_FLAGS_1=0x8000001")
1709
1710	// Separate the errors from the shim and those from tools like
1711	// AddressSanitizer.
1712	var extraStderr string
1713	if stderrParts := strings.SplitN(stderr, "--- DONE ---\n", 2); len(stderrParts) == 2 {
1714		stderr = stderrParts[0]
1715		extraStderr = stderrParts[1]
1716	}
1717
1718	failed := localErr != nil || childErr != nil
1719	expectedError := translateExpectedError(test.expectedError)
1720	correctFailure := len(expectedError) == 0 || strings.Contains(stderr, expectedError)
1721
1722	localErrString := "none"
1723	if localErr != nil {
1724		localErrString = localErr.Error()
1725	}
1726	if len(test.expectedLocalError) != 0 {
1727		correctFailure = correctFailure && strings.Contains(localErrString, test.expectedLocalError)
1728	}
1729
1730	if failed != test.shouldFail || failed && !correctFailure || mustFail {
1731		childErrString := "none"
1732		if childErr != nil {
1733			childErrString = childErr.Error()
1734		}
1735
1736		var msg string
1737		switch {
1738		case failed && !test.shouldFail:
1739			msg = "unexpected failure"
1740		case !failed && test.shouldFail:
1741			msg = "unexpected success"
1742		case failed && !correctFailure:
1743			msg = "bad error (wanted '" + expectedError + "' / '" + test.expectedLocalError + "')"
1744		case mustFail:
1745			msg = "test failure"
1746		default:
1747			panic("internal error")
1748		}
1749
1750		return fmt.Errorf("%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s\n%s", msg, localErrString, childErrString, stdout, stderr, extraStderr)
1751	}
1752
1753	if len(extraStderr) > 0 || (!failed && len(stderr) > 0) {
1754		return fmt.Errorf("unexpected error output:\n%s\n%s", stderr, extraStderr)
1755	}
1756
1757	if *useValgrind && isValgrindError {
1758		return fmt.Errorf("valgrind error:\n%s\n%s", stderr, extraStderr)
1759	}
1760
1761	return nil
1762}
1763
1764type tlsVersion struct {
1765	name string
1766	// version is the protocol version.
1767	version uint16
1768	// excludeFlag is the legacy shim flag to disable the version.
1769	excludeFlag string
1770	hasDTLS     bool
1771	hasQUIC     bool
1772	// versionDTLS, if non-zero, is the DTLS-specific representation of the version.
1773	versionDTLS uint16
1774	// versionWire, if non-zero, is the wire representation of the
1775	// version. Otherwise the wire version is the protocol version or
1776	// versionDTLS.
1777	versionWire uint16
1778}
1779
1780func (vers tlsVersion) String() string {
1781	return vers.name
1782}
1783
1784func (vers tlsVersion) shimFlag(protocol protocol) string {
1785	// The shim uses the protocol version in its public API, but uses the
1786	// DTLS-specific version if it exists.
1787	if protocol == dtls && vers.versionDTLS != 0 {
1788		return strconv.Itoa(int(vers.versionDTLS))
1789	}
1790	return strconv.Itoa(int(vers.version))
1791}
1792
1793func (vers tlsVersion) wire(protocol protocol) uint16 {
1794	if protocol == dtls && vers.versionDTLS != 0 {
1795		return vers.versionDTLS
1796	}
1797	if vers.versionWire != 0 {
1798		return vers.versionWire
1799	}
1800	return vers.version
1801}
1802
1803func (vers tlsVersion) supportsProtocol(protocol protocol) bool {
1804	if protocol == dtls {
1805		return vers.hasDTLS
1806	}
1807	if protocol == quic {
1808		return vers.hasQUIC
1809	}
1810	return true
1811}
1812
1813var tlsVersions = []tlsVersion{
1814	{
1815		name:        "TLS1",
1816		version:     VersionTLS10,
1817		excludeFlag: "-no-tls1",
1818		hasDTLS:     true,
1819		versionDTLS: VersionDTLS10,
1820	},
1821	{
1822		name:        "TLS11",
1823		version:     VersionTLS11,
1824		excludeFlag: "-no-tls11",
1825	},
1826	{
1827		name:        "TLS12",
1828		version:     VersionTLS12,
1829		excludeFlag: "-no-tls12",
1830		hasDTLS:     true,
1831		versionDTLS: VersionDTLS12,
1832	},
1833	{
1834		name:        "TLS13",
1835		version:     VersionTLS13,
1836		excludeFlag: "-no-tls13",
1837		hasQUIC:     true,
1838		versionWire: VersionTLS13,
1839	},
1840}
1841
1842func allVersions(protocol protocol) []tlsVersion {
1843	if protocol == tls {
1844		return tlsVersions
1845	}
1846
1847	var ret []tlsVersion
1848	for _, vers := range tlsVersions {
1849		if vers.supportsProtocol(protocol) {
1850			ret = append(ret, vers)
1851		}
1852	}
1853	return ret
1854}
1855
1856type testCipherSuite struct {
1857	name string
1858	id   uint16
1859}
1860
1861var testCipherSuites = []testCipherSuite{
1862	{"RSA_WITH_3DES_EDE_CBC_SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
1863	{"RSA_WITH_AES_128_GCM_SHA256", TLS_RSA_WITH_AES_128_GCM_SHA256},
1864	{"RSA_WITH_AES_128_CBC_SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
1865	{"RSA_WITH_AES_256_GCM_SHA384", TLS_RSA_WITH_AES_256_GCM_SHA384},
1866	{"RSA_WITH_AES_256_CBC_SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
1867	{"ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
1868	{"ECDHE_ECDSA_WITH_AES_128_CBC_SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
1869	{"ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384},
1870	{"ECDHE_ECDSA_WITH_AES_256_CBC_SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
1871	{"ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256},
1872	{"ECDHE_RSA_WITH_AES_128_GCM_SHA256", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
1873	{"ECDHE_RSA_WITH_AES_128_CBC_SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
1874	{"ECDHE_RSA_WITH_AES_128_CBC_SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
1875	{"ECDHE_RSA_WITH_AES_256_GCM_SHA384", TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384},
1876	{"ECDHE_RSA_WITH_AES_256_CBC_SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
1877	{"ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
1878	{"PSK_WITH_AES_128_CBC_SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
1879	{"PSK_WITH_AES_256_CBC_SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
1880	{"ECDHE_PSK_WITH_AES_128_CBC_SHA", TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
1881	{"ECDHE_PSK_WITH_AES_256_CBC_SHA", TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA},
1882	{"ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256", TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256},
1883	{"CHACHA20_POLY1305_SHA256", TLS_CHACHA20_POLY1305_SHA256},
1884	{"AES_128_GCM_SHA256", TLS_AES_128_GCM_SHA256},
1885	{"AES_256_GCM_SHA384", TLS_AES_256_GCM_SHA384},
1886}
1887
1888func hasComponent(suiteName, component string) bool {
1889	return strings.Contains("_"+suiteName+"_", "_"+component+"_")
1890}
1891
1892func isTLS12Only(suiteName string) bool {
1893	return hasComponent(suiteName, "GCM") ||
1894		hasComponent(suiteName, "SHA256") ||
1895		hasComponent(suiteName, "SHA384") ||
1896		hasComponent(suiteName, "POLY1305")
1897}
1898
1899func isTLS13Suite(suiteName string) bool {
1900	return !hasComponent(suiteName, "WITH")
1901}
1902
1903func bigFromHex(hex string) *big.Int {
1904	ret, ok := new(big.Int).SetString(hex, 16)
1905	if !ok {
1906		panic("failed to parse hex number 0x" + hex)
1907	}
1908	return ret
1909}
1910
1911func convertToSplitHandshakeTests(tests []testCase) (splitHandshakeTests []testCase, err error) {
1912	var stdout bytes.Buffer
1913	var flags []string
1914	if len(*shimExtraFlags) > 0 {
1915		flags = strings.Split(*shimExtraFlags, ";")
1916	}
1917	flags = append(flags, "-is-handshaker-supported")
1918	shim := exec.Command(*shimPath, flags...)
1919	shim.Stdout = &stdout
1920	if err := shim.Run(); err != nil {
1921		return nil, err
1922	}
1923
1924	switch strings.TrimSpace(string(stdout.Bytes())) {
1925	case "No":
1926		return
1927	case "Yes":
1928		break
1929	default:
1930		return nil, fmt.Errorf("unknown output from shim: %q", stdout.Bytes())
1931	}
1932
1933	var allowHintMismatchPattern []string
1934	if len(*allowHintMismatch) > 0 {
1935		allowHintMismatchPattern = strings.Split(*allowHintMismatch, ";")
1936	}
1937
1938NextTest:
1939	for _, test := range tests {
1940		if test.protocol != tls ||
1941			test.testType != serverTest ||
1942			len(test.shimCredentials) != 0 ||
1943			strings.Contains(test.name, "ECH-Server") ||
1944			test.skipSplitHandshake {
1945			continue
1946		}
1947
1948		for _, flag := range test.flags {
1949			if flag == "-implicit-handshake" {
1950				continue NextTest
1951			}
1952		}
1953
1954		shTest := test
1955		shTest.name += "-Split"
1956		shTest.flags = make([]string, len(test.flags), len(test.flags)+3)
1957		copy(shTest.flags, test.flags)
1958		shTest.flags = append(shTest.flags, "-handoff", "-handshaker-path", *handshakerPath)
1959
1960		splitHandshakeTests = append(splitHandshakeTests, shTest)
1961	}
1962
1963	for _, test := range tests {
1964		if test.protocol == dtls ||
1965			test.testType != serverTest ||
1966			test.skipHints {
1967			continue
1968		}
1969
1970		var matched bool
1971		if len(allowHintMismatchPattern) > 0 {
1972			matched, err = match(allowHintMismatchPattern, nil, test.name)
1973			if err != nil {
1974				return nil, fmt.Errorf("error matching pattern: %s", err)
1975			}
1976		}
1977
1978		shTest := test
1979		shTest.name += "-Hints"
1980		shTest.flags = make([]string, len(test.flags), len(test.flags)+3)
1981		copy(shTest.flags, test.flags)
1982		shTest.flags = append(shTest.flags, "-handshake-hints", "-handshaker-path", *handshakerPath)
1983		if matched {
1984			shTest.flags = append(shTest.flags, "-allow-hint-mismatch")
1985		}
1986
1987		splitHandshakeTests = append(splitHandshakeTests, shTest)
1988	}
1989
1990	return splitHandshakeTests, nil
1991}
1992
1993func addBasicTests() {
1994	basicTests := []testCase{
1995		{
1996			name: "NoFallbackSCSV",
1997			config: Config{
1998				Bugs: ProtocolBugs{
1999					FailIfNotFallbackSCSV: true,
2000				},
2001			},
2002			shouldFail:         true,
2003			expectedLocalError: "no fallback SCSV found",
2004		},
2005		{
2006			name: "SendFallbackSCSV",
2007			config: Config{
2008				Bugs: ProtocolBugs{
2009					FailIfNotFallbackSCSV: true,
2010				},
2011			},
2012			flags: []string{"-fallback-scsv"},
2013		},
2014		{
2015			name: "ClientCertificateTypes",
2016			config: Config{
2017				MaxVersion: VersionTLS12,
2018				ClientAuth: RequestClientCert,
2019				ClientCertificateTypes: []byte{
2020					CertTypeDSSSign,
2021					CertTypeRSASign,
2022					CertTypeECDSASign,
2023				},
2024			},
2025			flags: []string{
2026				"-expect-certificate-types",
2027				base64FlagValue([]byte{
2028					CertTypeDSSSign,
2029					CertTypeRSASign,
2030					CertTypeECDSASign,
2031				}),
2032			},
2033		},
2034		{
2035			name: "CheckClientCertificateTypes",
2036			config: Config{
2037				MaxVersion:             VersionTLS12,
2038				ClientAuth:             RequestClientCert,
2039				ClientCertificateTypes: []byte{CertTypeECDSASign},
2040			},
2041			shimCertificate: &rsaCertificate,
2042			shouldFail:      true,
2043			expectedError:   ":UNKNOWN_CERTIFICATE_TYPE:",
2044		},
2045		{
2046			name: "NoCheckClientCertificateTypes",
2047			config: Config{
2048				MaxVersion:             VersionTLS12,
2049				ClientAuth:             RequestClientCert,
2050				ClientCertificateTypes: []byte{CertTypeECDSASign},
2051			},
2052			shimCertificate: &rsaCertificate,
2053			flags:           []string{"-no-check-client-certificate-type"},
2054		},
2055		{
2056			name: "UnauthenticatedECDH",
2057			config: Config{
2058				MaxVersion:   VersionTLS12,
2059				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2060				Bugs: ProtocolBugs{
2061					UnauthenticatedECDH: true,
2062				},
2063			},
2064			shouldFail:    true,
2065			expectedError: ":UNEXPECTED_MESSAGE:",
2066		},
2067		{
2068			name: "SkipCertificateStatus",
2069			config: Config{
2070				MaxVersion:   VersionTLS12,
2071				Credential:   rsaCertificate.WithOCSP(testOCSPResponse),
2072				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2073				Bugs: ProtocolBugs{
2074					SkipCertificateStatus: true,
2075				},
2076			},
2077			flags: []string{
2078				"-enable-ocsp-stapling",
2079				// This test involves an optional message. Test the message callback
2080				// trace to ensure we do not miss or double-report any.
2081				"-expect-msg-callback",
2082				`write hs 1
2083read hs 2
2084read hs 11
2085read hs 12
2086read hs 14
2087write hs 16
2088write ccs
2089write hs 20
2090read hs 4
2091read ccs
2092read hs 20
2093read alert 1 0
2094`,
2095			},
2096		},
2097		{
2098			protocol: dtls,
2099			name:     "SkipCertificateStatus-DTLS",
2100			config: Config{
2101				MaxVersion:   VersionTLS12,
2102				Credential:   rsaCertificate.WithOCSP(testOCSPResponse),
2103				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2104				Bugs: ProtocolBugs{
2105					SkipCertificateStatus: true,
2106				},
2107			},
2108			flags: []string{
2109				"-enable-ocsp-stapling",
2110				// This test involves an optional message. Test the message callback
2111				// trace to ensure we do not miss or double-report any.
2112				"-expect-msg-callback",
2113				`write hs 1
2114read hs 3
2115write hs 1
2116read hs 2
2117read hs 11
2118read hs 12
2119read hs 14
2120write hs 16
2121write ccs
2122write hs 20
2123read hs 4
2124read ccs
2125read hs 20
2126read alert 1 0
2127`,
2128			},
2129		},
2130		{
2131			name: "SkipServerKeyExchange",
2132			config: Config{
2133				MaxVersion:   VersionTLS12,
2134				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2135				Bugs: ProtocolBugs{
2136					SkipServerKeyExchange: true,
2137				},
2138			},
2139			shouldFail:    true,
2140			expectedError: ":UNEXPECTED_MESSAGE:",
2141		},
2142		{
2143			testType: serverTest,
2144			name:     "ServerSkipCertificateVerify",
2145			config: Config{
2146				MaxVersion: VersionTLS12,
2147				Credential: &rsaCertificate,
2148				Bugs: ProtocolBugs{
2149					SkipCertificateVerify: true,
2150				},
2151			},
2152			expectations: connectionExpectations{
2153				peerCertificate: &rsaCertificate,
2154			},
2155			flags: []string{
2156				"-require-any-client-certificate",
2157			},
2158			shouldFail:         true,
2159			expectedError:      ":UNEXPECTED_RECORD:",
2160			expectedLocalError: "remote error: unexpected message",
2161		},
2162		{
2163			testType: serverTest,
2164			name:     "Alert",
2165			config: Config{
2166				Bugs: ProtocolBugs{
2167					SendSpuriousAlert: alertRecordOverflow,
2168				},
2169			},
2170			shouldFail:    true,
2171			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
2172		},
2173		{
2174			protocol: dtls,
2175			testType: serverTest,
2176			name:     "Alert-DTLS",
2177			config: Config{
2178				Bugs: ProtocolBugs{
2179					SendSpuriousAlert: alertRecordOverflow,
2180				},
2181			},
2182			shouldFail:    true,
2183			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
2184		},
2185		{
2186			testType: serverTest,
2187			name:     "FragmentAlert",
2188			config: Config{
2189				Bugs: ProtocolBugs{
2190					FragmentAlert:     true,
2191					SendSpuriousAlert: alertRecordOverflow,
2192				},
2193			},
2194			shouldFail:    true,
2195			expectedError: ":BAD_ALERT:",
2196		},
2197		{
2198			protocol: dtls,
2199			testType: serverTest,
2200			name:     "FragmentAlert-DTLS",
2201			config: Config{
2202				Bugs: ProtocolBugs{
2203					FragmentAlert:     true,
2204					SendSpuriousAlert: alertRecordOverflow,
2205				},
2206			},
2207			shouldFail:    true,
2208			expectedError: ":BAD_ALERT:",
2209		},
2210		{
2211			testType: serverTest,
2212			name:     "DoubleAlert",
2213			config: Config{
2214				Bugs: ProtocolBugs{
2215					DoubleAlert:       true,
2216					SendSpuriousAlert: alertRecordOverflow,
2217				},
2218			},
2219			shouldFail:    true,
2220			expectedError: ":BAD_ALERT:",
2221		},
2222		{
2223			protocol: dtls,
2224			testType: serverTest,
2225			name:     "DoubleAlert-DTLS",
2226			config: Config{
2227				Bugs: ProtocolBugs{
2228					DoubleAlert:       true,
2229					SendSpuriousAlert: alertRecordOverflow,
2230				},
2231			},
2232			shouldFail:    true,
2233			expectedError: ":BAD_ALERT:",
2234		},
2235		{
2236			name: "SkipNewSessionTicket",
2237			config: Config{
2238				MaxVersion: VersionTLS12,
2239				Bugs: ProtocolBugs{
2240					SkipNewSessionTicket: true,
2241				},
2242			},
2243			shouldFail:    true,
2244			expectedError: ":UNEXPECTED_RECORD:",
2245		},
2246		{
2247			testType: serverTest,
2248			name:     "FallbackSCSV",
2249			config: Config{
2250				MaxVersion: VersionTLS11,
2251				Bugs: ProtocolBugs{
2252					SendFallbackSCSV: true,
2253				},
2254			},
2255			shouldFail:         true,
2256			expectedError:      ":INAPPROPRIATE_FALLBACK:",
2257			expectedLocalError: "remote error: inappropriate fallback",
2258		},
2259		{
2260			testType: serverTest,
2261			name:     "FallbackSCSV-VersionMatch-TLS13",
2262			config: Config{
2263				MaxVersion: VersionTLS13,
2264				Bugs: ProtocolBugs{
2265					SendFallbackSCSV: true,
2266				},
2267			},
2268		},
2269		{
2270			testType: serverTest,
2271			name:     "FallbackSCSV-VersionMatch-TLS12",
2272			config: Config{
2273				MaxVersion: VersionTLS12,
2274				Bugs: ProtocolBugs{
2275					SendFallbackSCSV: true,
2276				},
2277			},
2278			flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
2279		},
2280		{
2281			testType: serverTest,
2282			name:     "FragmentedClientVersion",
2283			config: Config{
2284				Bugs: ProtocolBugs{
2285					MaxHandshakeRecordLength: 1,
2286					FragmentClientVersion:    true,
2287				},
2288			},
2289			expectations: connectionExpectations{
2290				version: VersionTLS13,
2291			},
2292		},
2293		{
2294			testType:      serverTest,
2295			name:          "HttpGET",
2296			sendPrefix:    "GET / HTTP/1.0\n",
2297			shouldFail:    true,
2298			expectedError: ":HTTP_REQUEST:",
2299		},
2300		{
2301			testType:      serverTest,
2302			name:          "HttpPOST",
2303			sendPrefix:    "POST / HTTP/1.0\n",
2304			shouldFail:    true,
2305			expectedError: ":HTTP_REQUEST:",
2306		},
2307		{
2308			testType:      serverTest,
2309			name:          "HttpHEAD",
2310			sendPrefix:    "HEAD / HTTP/1.0\n",
2311			shouldFail:    true,
2312			expectedError: ":HTTP_REQUEST:",
2313		},
2314		{
2315			testType:      serverTest,
2316			name:          "HttpPUT",
2317			sendPrefix:    "PUT / HTTP/1.0\n",
2318			shouldFail:    true,
2319			expectedError: ":HTTP_REQUEST:",
2320		},
2321		{
2322			testType:      serverTest,
2323			name:          "HttpCONNECT",
2324			sendPrefix:    "CONNECT www.google.com:443 HTTP/1.0\n",
2325			shouldFail:    true,
2326			expectedError: ":HTTPS_PROXY_REQUEST:",
2327		},
2328		{
2329			testType:      serverTest,
2330			name:          "Garbage",
2331			sendPrefix:    "blah",
2332			shouldFail:    true,
2333			expectedError: ":WRONG_VERSION_NUMBER:",
2334		},
2335		{
2336			name: "RSAEphemeralKey",
2337			config: Config{
2338				MaxVersion:   VersionTLS12,
2339				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
2340				Bugs: ProtocolBugs{
2341					RSAEphemeralKey: true,
2342				},
2343			},
2344			shouldFail:    true,
2345			expectedError: ":UNEXPECTED_MESSAGE:",
2346		},
2347		{
2348			name:          "DisableEverything",
2349			flags:         []string{"-no-tls13", "-no-tls12", "-no-tls11", "-no-tls1"},
2350			shouldFail:    true,
2351			expectedError: ":NO_SUPPORTED_VERSIONS_ENABLED:",
2352		},
2353		{
2354			protocol:      dtls,
2355			name:          "DisableEverything-DTLS",
2356			flags:         []string{"-no-tls12", "-no-tls1"},
2357			shouldFail:    true,
2358			expectedError: ":NO_SUPPORTED_VERSIONS_ENABLED:",
2359		},
2360		{
2361			protocol: dtls,
2362			testType: serverTest,
2363			name:     "MTU",
2364			config: Config{
2365				Bugs: ProtocolBugs{
2366					MaxPacketLength: 256,
2367				},
2368			},
2369			flags: []string{"-mtu", "256"},
2370		},
2371		{
2372			protocol: dtls,
2373			testType: serverTest,
2374			name:     "MTUExceeded",
2375			config: Config{
2376				Bugs: ProtocolBugs{
2377					MaxPacketLength: 255,
2378				},
2379			},
2380			flags:              []string{"-mtu", "256"},
2381			shouldFail:         true,
2382			expectedLocalError: "dtls: exceeded maximum packet length",
2383		},
2384		{
2385			name: "EmptyCertificateList",
2386			config: Config{
2387				MaxVersion: VersionTLS12,
2388				Bugs: ProtocolBugs{
2389					EmptyCertificateList: true,
2390				},
2391			},
2392			shouldFail:    true,
2393			expectedError: ":DECODE_ERROR:",
2394		},
2395		{
2396			name: "EmptyCertificateList-TLS13",
2397			config: Config{
2398				MaxVersion: VersionTLS13,
2399				Bugs: ProtocolBugs{
2400					EmptyCertificateList: true,
2401				},
2402			},
2403			shouldFail:    true,
2404			expectedError: ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
2405		},
2406		{
2407			name:             "TLSFatalBadPackets",
2408			damageFirstWrite: true,
2409			shouldFail:       true,
2410			expectedError:    ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
2411		},
2412		{
2413			protocol:         dtls,
2414			name:             "DTLSIgnoreBadPackets",
2415			damageFirstWrite: true,
2416		},
2417		{
2418			protocol:         dtls,
2419			name:             "DTLSIgnoreBadPackets-Async",
2420			damageFirstWrite: true,
2421			flags:            []string{"-async"},
2422		},
2423		{
2424			name: "AppDataBeforeHandshake",
2425			config: Config{
2426				Bugs: ProtocolBugs{
2427					AppDataBeforeHandshake: []byte("TEST MESSAGE"),
2428				},
2429			},
2430			shouldFail:    true,
2431			expectedError: ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:",
2432		},
2433		{
2434			name: "AppDataBeforeHandshake-Empty",
2435			config: Config{
2436				Bugs: ProtocolBugs{
2437					AppDataBeforeHandshake: []byte{},
2438				},
2439			},
2440			shouldFail:    true,
2441			expectedError: ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:",
2442		},
2443		{
2444			protocol: dtls,
2445			name:     "AppDataBeforeHandshake-DTLS",
2446			config: Config{
2447				Bugs: ProtocolBugs{
2448					AppDataBeforeHandshake: []byte("TEST MESSAGE"),
2449				},
2450			},
2451			shouldFail:    true,
2452			expectedError: ":UNEXPECTED_RECORD:",
2453		},
2454		{
2455			protocol: dtls,
2456			name:     "AppDataBeforeHandshake-DTLS-Empty",
2457			config: Config{
2458				Bugs: ProtocolBugs{
2459					AppDataBeforeHandshake: []byte{},
2460				},
2461			},
2462			shouldFail:    true,
2463			expectedError: ":UNEXPECTED_RECORD:",
2464		},
2465		{
2466			name: "AppDataAfterChangeCipherSpec",
2467			config: Config{
2468				MaxVersion: VersionTLS12,
2469				Bugs: ProtocolBugs{
2470					AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
2471				},
2472			},
2473			shouldFail:    true,
2474			expectedError: ":UNEXPECTED_RECORD:",
2475		},
2476		{
2477			name: "AppDataAfterChangeCipherSpec-Empty",
2478			config: Config{
2479				MaxVersion: VersionTLS12,
2480				Bugs: ProtocolBugs{
2481					AppDataAfterChangeCipherSpec: []byte{},
2482				},
2483			},
2484			shouldFail:    true,
2485			expectedError: ":UNEXPECTED_RECORD:",
2486		},
2487		{
2488			protocol: dtls,
2489			name:     "AppDataAfterChangeCipherSpec-DTLS",
2490			config: Config{
2491				MaxVersion: VersionTLS12,
2492				Bugs: ProtocolBugs{
2493					AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
2494				},
2495			},
2496			// BoringSSL's DTLS implementation will drop the out-of-order
2497			// application data.
2498		},
2499		{
2500			protocol: dtls,
2501			name:     "AppDataAfterChangeCipherSpec-DTLS-Empty",
2502			config: Config{
2503				MaxVersion: VersionTLS12,
2504				Bugs: ProtocolBugs{
2505					AppDataAfterChangeCipherSpec: []byte{},
2506				},
2507			},
2508			// BoringSSL's DTLS implementation will drop the out-of-order
2509			// application data.
2510		},
2511		{
2512			name: "AlertAfterChangeCipherSpec",
2513			config: Config{
2514				MaxVersion: VersionTLS12,
2515				Bugs: ProtocolBugs{
2516					AlertAfterChangeCipherSpec: alertRecordOverflow,
2517				},
2518			},
2519			shouldFail:    true,
2520			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
2521		},
2522		{
2523			protocol: dtls,
2524			name:     "AlertAfterChangeCipherSpec-DTLS",
2525			config: Config{
2526				MaxVersion: VersionTLS12,
2527				Bugs: ProtocolBugs{
2528					AlertAfterChangeCipherSpec: alertRecordOverflow,
2529				},
2530			},
2531			shouldFail:    true,
2532			expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
2533		},
2534		{
2535			protocol: dtls,
2536			name:     "ReorderHandshakeFragments-Small-DTLS",
2537			config: Config{
2538				Bugs: ProtocolBugs{
2539					ReorderHandshakeFragments: true,
2540					// Small enough that every handshake message is
2541					// fragmented.
2542					MaxHandshakeRecordLength: 2,
2543				},
2544			},
2545		},
2546		{
2547			protocol: dtls,
2548			name:     "ReorderHandshakeFragments-Large-DTLS",
2549			config: Config{
2550				Bugs: ProtocolBugs{
2551					ReorderHandshakeFragments: true,
2552					// Large enough that no handshake message is
2553					// fragmented.
2554					MaxHandshakeRecordLength: 2048,
2555				},
2556			},
2557		},
2558		{
2559			protocol: dtls,
2560			name:     "MixCompleteMessageWithFragments-DTLS",
2561			config: Config{
2562				Bugs: ProtocolBugs{
2563					ReorderHandshakeFragments:       true,
2564					MixCompleteMessageWithFragments: true,
2565					MaxHandshakeRecordLength:        2,
2566				},
2567			},
2568		},
2569		{
2570			name: "SendInvalidRecordType",
2571			config: Config{
2572				Bugs: ProtocolBugs{
2573					SendInvalidRecordType: true,
2574				},
2575			},
2576			shouldFail:    true,
2577			expectedError: ":UNEXPECTED_RECORD:",
2578		},
2579		{
2580			protocol: dtls,
2581			name:     "SendInvalidRecordType-DTLS",
2582			config: Config{
2583				Bugs: ProtocolBugs{
2584					SendInvalidRecordType: true,
2585				},
2586			},
2587			shouldFail:    true,
2588			expectedError: ":UNEXPECTED_RECORD:",
2589		},
2590		{
2591			name: "FalseStart-SkipServerSecondLeg",
2592			config: Config{
2593				MaxVersion:   VersionTLS12,
2594				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2595				NextProtos:   []string{"foo"},
2596				Bugs: ProtocolBugs{
2597					SkipNewSessionTicket: true,
2598					SkipChangeCipherSpec: true,
2599					SkipFinished:         true,
2600					ExpectFalseStart:     true,
2601				},
2602			},
2603			flags: []string{
2604				"-false-start",
2605				"-handshake-never-done",
2606				"-advertise-alpn", "\x03foo",
2607				"-expect-alpn", "foo",
2608			},
2609			shimWritesFirst: true,
2610			shouldFail:      true,
2611			expectedError:   ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:",
2612		},
2613		{
2614			name: "FalseStart-SkipServerSecondLeg-Implicit",
2615			config: Config{
2616				MaxVersion:   VersionTLS12,
2617				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2618				NextProtos:   []string{"foo"},
2619				Bugs: ProtocolBugs{
2620					SkipNewSessionTicket: true,
2621					SkipChangeCipherSpec: true,
2622					SkipFinished:         true,
2623				},
2624			},
2625			flags: []string{
2626				"-implicit-handshake",
2627				"-false-start",
2628				"-handshake-never-done",
2629				"-advertise-alpn", "\x03foo",
2630			},
2631			shouldFail:    true,
2632			expectedError: ":APPLICATION_DATA_INSTEAD_OF_HANDSHAKE:",
2633		},
2634		{
2635			testType:           serverTest,
2636			name:               "FailEarlyCallback",
2637			flags:              []string{"-fail-early-callback"},
2638			shouldFail:         true,
2639			expectedError:      ":CONNECTION_REJECTED:",
2640			expectedLocalError: "remote error: handshake failure",
2641		},
2642		{
2643			name: "FailCertCallback-Client-TLS12",
2644			config: Config{
2645				MaxVersion: VersionTLS12,
2646				ClientAuth: RequestClientCert,
2647			},
2648			flags:              []string{"-fail-cert-callback"},
2649			shouldFail:         true,
2650			expectedError:      ":CERT_CB_ERROR:",
2651			expectedLocalError: "remote error: internal error",
2652		},
2653		{
2654			testType: serverTest,
2655			name:     "FailCertCallback-Server-TLS12",
2656			config: Config{
2657				MaxVersion: VersionTLS12,
2658			},
2659			flags:              []string{"-fail-cert-callback"},
2660			shouldFail:         true,
2661			expectedError:      ":CERT_CB_ERROR:",
2662			expectedLocalError: "remote error: internal error",
2663		},
2664		{
2665			name: "FailCertCallback-Client-TLS13",
2666			config: Config{
2667				MaxVersion: VersionTLS13,
2668				ClientAuth: RequestClientCert,
2669			},
2670			flags:              []string{"-fail-cert-callback"},
2671			shouldFail:         true,
2672			expectedError:      ":CERT_CB_ERROR:",
2673			expectedLocalError: "remote error: internal error",
2674		},
2675		{
2676			testType: serverTest,
2677			name:     "FailCertCallback-Server-TLS13",
2678			config: Config{
2679				MaxVersion: VersionTLS13,
2680			},
2681			flags:              []string{"-fail-cert-callback"},
2682			shouldFail:         true,
2683			expectedError:      ":CERT_CB_ERROR:",
2684			expectedLocalError: "remote error: internal error",
2685		},
2686		{
2687			protocol: dtls,
2688			name:     "FragmentMessageTypeMismatch-DTLS",
2689			config: Config{
2690				Bugs: ProtocolBugs{
2691					MaxHandshakeRecordLength:    2,
2692					FragmentMessageTypeMismatch: true,
2693				},
2694			},
2695			shouldFail:    true,
2696			expectedError: ":FRAGMENT_MISMATCH:",
2697		},
2698		{
2699			protocol: dtls,
2700			name:     "FragmentMessageLengthMismatch-DTLS",
2701			config: Config{
2702				Bugs: ProtocolBugs{
2703					MaxHandshakeRecordLength:      2,
2704					FragmentMessageLengthMismatch: true,
2705				},
2706			},
2707			shouldFail:    true,
2708			expectedError: ":FRAGMENT_MISMATCH:",
2709		},
2710		{
2711			protocol: dtls,
2712			name:     "SplitFragments-Header-DTLS",
2713			config: Config{
2714				Bugs: ProtocolBugs{
2715					SplitFragments: 2,
2716				},
2717			},
2718			shouldFail:    true,
2719			expectedError: ":BAD_HANDSHAKE_RECORD:",
2720		},
2721		{
2722			protocol: dtls,
2723			name:     "SplitFragments-Boundary-DTLS",
2724			config: Config{
2725				Bugs: ProtocolBugs{
2726					SplitFragments: dtlsRecordHeaderLen,
2727				},
2728			},
2729			shouldFail:    true,
2730			expectedError: ":BAD_HANDSHAKE_RECORD:",
2731		},
2732		{
2733			protocol: dtls,
2734			name:     "SplitFragments-Body-DTLS",
2735			config: Config{
2736				Bugs: ProtocolBugs{
2737					SplitFragments: dtlsRecordHeaderLen + 1,
2738				},
2739			},
2740			shouldFail:    true,
2741			expectedError: ":BAD_HANDSHAKE_RECORD:",
2742		},
2743		{
2744			protocol: dtls,
2745			name:     "SendEmptyFragments-DTLS",
2746			config: Config{
2747				Bugs: ProtocolBugs{
2748					SendEmptyFragments: true,
2749				},
2750			},
2751		},
2752		{
2753			testType: serverTest,
2754			protocol: dtls,
2755			name:     "SendEmptyFragments-Padded-DTLS",
2756			config: Config{
2757				Bugs: ProtocolBugs{
2758					// Test empty fragments for a message with a
2759					// nice power-of-two length.
2760					PadClientHello:     64,
2761					SendEmptyFragments: true,
2762				},
2763			},
2764		},
2765		{
2766			name: "BadFinished-Client",
2767			config: Config{
2768				MaxVersion: VersionTLS12,
2769				Bugs: ProtocolBugs{
2770					BadFinished: true,
2771				},
2772			},
2773			shouldFail:    true,
2774			expectedError: ":DIGEST_CHECK_FAILED:",
2775		},
2776		{
2777			name: "BadFinished-Client-TLS13",
2778			config: Config{
2779				MaxVersion: VersionTLS13,
2780				Bugs: ProtocolBugs{
2781					BadFinished: true,
2782				},
2783			},
2784			shouldFail:    true,
2785			expectedError: ":DIGEST_CHECK_FAILED:",
2786		},
2787		{
2788			testType: serverTest,
2789			name:     "BadFinished-Server",
2790			config: Config{
2791				MaxVersion: VersionTLS12,
2792				Bugs: ProtocolBugs{
2793					BadFinished: true,
2794				},
2795			},
2796			shouldFail:    true,
2797			expectedError: ":DIGEST_CHECK_FAILED:",
2798		},
2799		{
2800			testType: serverTest,
2801			name:     "BadFinished-Server-TLS13",
2802			config: Config{
2803				MaxVersion: VersionTLS13,
2804				Bugs: ProtocolBugs{
2805					BadFinished: true,
2806				},
2807			},
2808			shouldFail:    true,
2809			expectedError: ":DIGEST_CHECK_FAILED:",
2810		},
2811		{
2812			name: "FalseStart-BadFinished",
2813			config: Config{
2814				MaxVersion:   VersionTLS12,
2815				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2816				NextProtos:   []string{"foo"},
2817				Bugs: ProtocolBugs{
2818					BadFinished:      true,
2819					ExpectFalseStart: true,
2820				},
2821			},
2822			flags: []string{
2823				"-false-start",
2824				"-handshake-never-done",
2825				"-advertise-alpn", "\x03foo",
2826				"-expect-alpn", "foo",
2827			},
2828			shimWritesFirst: true,
2829			shouldFail:      true,
2830			expectedError:   ":DIGEST_CHECK_FAILED:",
2831		},
2832		{
2833			name: "NoFalseStart-NoALPN",
2834			config: Config{
2835				MaxVersion:   VersionTLS12,
2836				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2837				Bugs: ProtocolBugs{
2838					ExpectFalseStart:          true,
2839					AlertBeforeFalseStartTest: alertAccessDenied,
2840				},
2841			},
2842			flags: []string{
2843				"-false-start",
2844			},
2845			shimWritesFirst:    true,
2846			shouldFail:         true,
2847			expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
2848			expectedLocalError: "tls: peer did not false start: EOF",
2849		},
2850		{
2851			name: "FalseStart-NoALPNAllowed",
2852			config: Config{
2853				MaxVersion:   VersionTLS12,
2854				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
2855				Bugs: ProtocolBugs{
2856					ExpectFalseStart: true,
2857				},
2858			},
2859			flags: []string{
2860				"-false-start",
2861				"-allow-false-start-without-alpn",
2862			},
2863			shimWritesFirst: true,
2864		},
2865		{
2866			name: "NoFalseStart-NoAEAD",
2867			config: Config{
2868				MaxVersion:   VersionTLS12,
2869				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
2870				NextProtos:   []string{"foo"},
2871				Bugs: ProtocolBugs{
2872					ExpectFalseStart:          true,
2873					AlertBeforeFalseStartTest: alertAccessDenied,
2874				},
2875			},
2876			flags: []string{
2877				"-false-start",
2878				"-advertise-alpn", "\x03foo",
2879			},
2880			shimWritesFirst:    true,
2881			shouldFail:         true,
2882			expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
2883			expectedLocalError: "tls: peer did not false start: EOF",
2884		},
2885		{
2886			name: "NoFalseStart-RSA",
2887			config: Config{
2888				MaxVersion:   VersionTLS12,
2889				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
2890				NextProtos:   []string{"foo"},
2891				Bugs: ProtocolBugs{
2892					ExpectFalseStart:          true,
2893					AlertBeforeFalseStartTest: alertAccessDenied,
2894				},
2895			},
2896			flags: []string{
2897				"-false-start",
2898				"-advertise-alpn", "\x03foo",
2899			},
2900			shimWritesFirst:    true,
2901			shouldFail:         true,
2902			expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
2903			expectedLocalError: "tls: peer did not false start: EOF",
2904		},
2905		{
2906			protocol: dtls,
2907			name:     "SendSplitAlert-Sync",
2908			config: Config{
2909				Bugs: ProtocolBugs{
2910					SendSplitAlert: true,
2911				},
2912			},
2913		},
2914		{
2915			protocol: dtls,
2916			name:     "SendSplitAlert-Async",
2917			config: Config{
2918				Bugs: ProtocolBugs{
2919					SendSplitAlert: true,
2920				},
2921			},
2922			flags: []string{"-async"},
2923		},
2924		{
2925			name:             "SendEmptyRecords-Pass",
2926			sendEmptyRecords: 32,
2927		},
2928		{
2929			name:             "SendEmptyRecords",
2930			sendEmptyRecords: 33,
2931			shouldFail:       true,
2932			expectedError:    ":TOO_MANY_EMPTY_FRAGMENTS:",
2933		},
2934		{
2935			name:             "SendEmptyRecords-Async",
2936			sendEmptyRecords: 33,
2937			flags:            []string{"-async"},
2938			shouldFail:       true,
2939			expectedError:    ":TOO_MANY_EMPTY_FRAGMENTS:",
2940		},
2941		{
2942			name: "SendWarningAlerts-Pass",
2943			config: Config{
2944				MaxVersion: VersionTLS12,
2945			},
2946			sendWarningAlerts: 4,
2947		},
2948		{
2949			protocol: dtls,
2950			name:     "SendWarningAlerts-DTLS-Pass",
2951			config: Config{
2952				MaxVersion: VersionTLS12,
2953			},
2954			sendWarningAlerts: 4,
2955		},
2956		{
2957			name: "SendWarningAlerts-TLS13",
2958			config: Config{
2959				MaxVersion: VersionTLS13,
2960			},
2961			sendWarningAlerts:  4,
2962			shouldFail:         true,
2963			expectedError:      ":BAD_ALERT:",
2964			expectedLocalError: "remote error: error decoding message",
2965		},
2966		// Although TLS 1.3 intended to remove warning alerts, it left in
2967		// user_canceled. JDK11 misuses this alert as a post-handshake
2968		// full-duplex signal. As a workaround, skip user_canceled as in
2969		// TLS 1.2, which is consistent with NSS and OpenSSL.
2970		{
2971			name: "SendUserCanceledAlerts-TLS13",
2972			config: Config{
2973				MaxVersion: VersionTLS13,
2974			},
2975			sendUserCanceledAlerts: 4,
2976		},
2977		{
2978			name: "SendUserCanceledAlerts-TooMany-TLS13",
2979			config: Config{
2980				MaxVersion: VersionTLS13,
2981			},
2982			sendUserCanceledAlerts: 5,
2983			shouldFail:             true,
2984			expectedError:          ":TOO_MANY_WARNING_ALERTS:",
2985		},
2986		{
2987			name: "SendWarningAlerts-TooMany",
2988			config: Config{
2989				MaxVersion: VersionTLS12,
2990			},
2991			sendWarningAlerts: 5,
2992			shouldFail:        true,
2993			expectedError:     ":TOO_MANY_WARNING_ALERTS:",
2994		},
2995		{
2996			name: "SendWarningAlerts-TooMany-Async",
2997			config: Config{
2998				MaxVersion: VersionTLS12,
2999			},
3000			sendWarningAlerts: 5,
3001			flags:             []string{"-async"},
3002			shouldFail:        true,
3003			expectedError:     ":TOO_MANY_WARNING_ALERTS:",
3004		},
3005		{
3006			name:               "SendBogusAlertType",
3007			sendBogusAlertType: true,
3008			shouldFail:         true,
3009			expectedError:      ":UNKNOWN_ALERT_TYPE:",
3010			expectedLocalError: "remote error: illegal parameter",
3011		},
3012		{
3013			protocol:           dtls,
3014			name:               "SendBogusAlertType-DTLS",
3015			sendBogusAlertType: true,
3016			shouldFail:         true,
3017			expectedError:      ":UNKNOWN_ALERT_TYPE:",
3018			expectedLocalError: "remote error: illegal parameter",
3019		},
3020		{
3021			name: "TooManyKeyUpdates",
3022			config: Config{
3023				MaxVersion: VersionTLS13,
3024			},
3025			sendKeyUpdates:   33,
3026			keyUpdateRequest: keyUpdateNotRequested,
3027			shouldFail:       true,
3028			expectedError:    ":TOO_MANY_KEY_UPDATES:",
3029		},
3030		{
3031			name: "EmptySessionID",
3032			config: Config{
3033				MaxVersion:             VersionTLS12,
3034				SessionTicketsDisabled: true,
3035			},
3036			noSessionCache: true,
3037			flags:          []string{"-expect-no-session"},
3038		},
3039		{
3040			name: "Unclean-Shutdown",
3041			config: Config{
3042				Bugs: ProtocolBugs{
3043					NoCloseNotify:     true,
3044					ExpectCloseNotify: true,
3045				},
3046			},
3047			shimShutsDown: true,
3048			flags:         []string{"-check-close-notify"},
3049			shouldFail:    true,
3050			expectedError: "Unexpected SSL_shutdown result: -1 != 1",
3051		},
3052		{
3053			name: "Unclean-Shutdown-Ignored",
3054			config: Config{
3055				Bugs: ProtocolBugs{
3056					NoCloseNotify: true,
3057				},
3058			},
3059			shimShutsDown: true,
3060		},
3061		{
3062			name: "Unclean-Shutdown-Alert",
3063			config: Config{
3064				Bugs: ProtocolBugs{
3065					SendAlertOnShutdown: alertDecompressionFailure,
3066					ExpectCloseNotify:   true,
3067				},
3068			},
3069			shimShutsDown: true,
3070			flags:         []string{"-check-close-notify"},
3071			shouldFail:    true,
3072			expectedError: ":SSLV3_ALERT_DECOMPRESSION_FAILURE:",
3073		},
3074		{
3075			name: "LargePlaintext",
3076			config: Config{
3077				Bugs: ProtocolBugs{
3078					SendLargeRecords: true,
3079				},
3080			},
3081			messageLen:         maxPlaintext + 1,
3082			shouldFail:         true,
3083			expectedError:      ":DATA_LENGTH_TOO_LONG:",
3084			expectedLocalError: "remote error: record overflow",
3085		},
3086		{
3087			protocol: dtls,
3088			name:     "LargePlaintext-DTLS",
3089			config: Config{
3090				Bugs: ProtocolBugs{
3091					SendLargeRecords: true,
3092				},
3093			},
3094			messageLen:         maxPlaintext + 1,
3095			shouldFail:         true,
3096			expectedError:      ":DATA_LENGTH_TOO_LONG:",
3097			expectedLocalError: "remote error: record overflow",
3098		},
3099		{
3100			name: "LargePlaintext-TLS13-Padded-8192-8192",
3101			config: Config{
3102				MinVersion: VersionTLS13,
3103				MaxVersion: VersionTLS13,
3104				Bugs: ProtocolBugs{
3105					RecordPadding:    8192,
3106					SendLargeRecords: true,
3107				},
3108			},
3109			messageLen: 8192,
3110		},
3111		{
3112			name: "LargePlaintext-TLS13-Padded-8193-8192",
3113			config: Config{
3114				MinVersion: VersionTLS13,
3115				MaxVersion: VersionTLS13,
3116				Bugs: ProtocolBugs{
3117					RecordPadding:    8193,
3118					SendLargeRecords: true,
3119				},
3120			},
3121			messageLen:         8192,
3122			shouldFail:         true,
3123			expectedError:      ":DATA_LENGTH_TOO_LONG:",
3124			expectedLocalError: "remote error: record overflow",
3125		},
3126		{
3127			name: "LargePlaintext-TLS13-Padded-16383-1",
3128			config: Config{
3129				MinVersion: VersionTLS13,
3130				MaxVersion: VersionTLS13,
3131				Bugs: ProtocolBugs{
3132					RecordPadding:    1,
3133					SendLargeRecords: true,
3134				},
3135			},
3136			messageLen: 16383,
3137		},
3138		{
3139			name: "LargePlaintext-TLS13-Padded-16384-1",
3140			config: Config{
3141				MinVersion: VersionTLS13,
3142				MaxVersion: VersionTLS13,
3143				Bugs: ProtocolBugs{
3144					RecordPadding:    1,
3145					SendLargeRecords: true,
3146				},
3147			},
3148			messageLen:         16384,
3149			shouldFail:         true,
3150			expectedError:      ":DATA_LENGTH_TOO_LONG:",
3151			expectedLocalError: "remote error: record overflow",
3152		},
3153		{
3154			name: "LargeCiphertext",
3155			config: Config{
3156				Bugs: ProtocolBugs{
3157					SendLargeRecords: true,
3158				},
3159			},
3160			messageLen:    maxPlaintext * 2,
3161			shouldFail:    true,
3162			expectedError: ":ENCRYPTED_LENGTH_TOO_LONG:",
3163		},
3164		{
3165			protocol: dtls,
3166			name:     "LargeCiphertext-DTLS",
3167			config: Config{
3168				Bugs: ProtocolBugs{
3169					SendLargeRecords: true,
3170				},
3171			},
3172			messageLen: maxPlaintext * 2,
3173			// Unlike the other four cases, DTLS drops records which
3174			// are invalid before authentication, so the connection
3175			// does not fail.
3176			expectMessageDropped: true,
3177		},
3178		{
3179			name:        "BadHelloRequest-1",
3180			renegotiate: 1,
3181			config: Config{
3182				MaxVersion: VersionTLS12,
3183				Bugs: ProtocolBugs{
3184					BadHelloRequest: []byte{typeHelloRequest, 0, 0, 1, 1},
3185				},
3186			},
3187			flags: []string{
3188				"-renegotiate-freely",
3189				"-expect-total-renegotiations", "1",
3190			},
3191			shouldFail:    true,
3192			expectedError: ":BAD_HELLO_REQUEST:",
3193		},
3194		{
3195			name:        "BadHelloRequest-2",
3196			renegotiate: 1,
3197			config: Config{
3198				MaxVersion: VersionTLS12,
3199				Bugs: ProtocolBugs{
3200					BadHelloRequest: []byte{typeServerKeyExchange, 0, 0, 0},
3201				},
3202			},
3203			flags: []string{
3204				"-renegotiate-freely",
3205				"-expect-total-renegotiations", "1",
3206			},
3207			shouldFail:    true,
3208			expectedError: ":BAD_HELLO_REQUEST:",
3209		},
3210		{
3211			testType: serverTest,
3212			name:     "SupportTicketsWithSessionID",
3213			config: Config{
3214				MaxVersion:             VersionTLS12,
3215				SessionTicketsDisabled: true,
3216			},
3217			resumeConfig: &Config{
3218				MaxVersion: VersionTLS12,
3219			},
3220			resumeSession: true,
3221		},
3222		{
3223			protocol: dtls,
3224			name:     "DTLS-SendExtraFinished",
3225			config: Config{
3226				Bugs: ProtocolBugs{
3227					SendExtraFinished: true,
3228				},
3229			},
3230			shouldFail:    true,
3231			expectedError: ":UNEXPECTED_RECORD:",
3232		},
3233		{
3234			protocol: dtls,
3235			name:     "DTLS-SendExtraFinished-Reordered",
3236			config: Config{
3237				Bugs: ProtocolBugs{
3238					MaxHandshakeRecordLength:  2,
3239					ReorderHandshakeFragments: true,
3240					SendExtraFinished:         true,
3241				},
3242			},
3243			shouldFail:    true,
3244			expectedError: ":UNEXPECTED_RECORD:",
3245		},
3246		{
3247			testType: serverTest,
3248			name:     "V2ClientHello-EmptyRecordPrefix",
3249			config: Config{
3250				// Choose a cipher suite that does not involve
3251				// elliptic curves, so no extensions are
3252				// involved.
3253				MaxVersion:   VersionTLS12,
3254				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3255				Bugs: ProtocolBugs{
3256					SendV2ClientHello: true,
3257				},
3258			},
3259			sendPrefix: string([]byte{
3260				byte(recordTypeHandshake),
3261				3, 1, // version
3262				0, 0, // length
3263			}),
3264			// A no-op empty record may not be sent before V2ClientHello.
3265			shouldFail:    true,
3266			expectedError: ":WRONG_VERSION_NUMBER:",
3267		},
3268		{
3269			testType: serverTest,
3270			name:     "V2ClientHello-WarningAlertPrefix",
3271			config: Config{
3272				// Choose a cipher suite that does not involve
3273				// elliptic curves, so no extensions are
3274				// involved.
3275				MaxVersion:   VersionTLS12,
3276				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3277				Bugs: ProtocolBugs{
3278					SendV2ClientHello: true,
3279				},
3280			},
3281			sendPrefix: string([]byte{
3282				byte(recordTypeAlert),
3283				3, 1, // version
3284				0, 2, // length
3285				alertLevelWarning, byte(alertDecompressionFailure),
3286			}),
3287			// A no-op warning alert may not be sent before V2ClientHello.
3288			shouldFail:    true,
3289			expectedError: ":WRONG_VERSION_NUMBER:",
3290		},
3291		{
3292			name: "KeyUpdate-ToClient",
3293			config: Config{
3294				MaxVersion: VersionTLS13,
3295			},
3296			sendKeyUpdates:   1,
3297			keyUpdateRequest: keyUpdateNotRequested,
3298		},
3299		{
3300			testType: serverTest,
3301			name:     "KeyUpdate-ToServer",
3302			config: Config{
3303				MaxVersion: VersionTLS13,
3304			},
3305			sendKeyUpdates:   1,
3306			keyUpdateRequest: keyUpdateNotRequested,
3307		},
3308		{
3309			name: "KeyUpdate-FromClient",
3310			config: Config{
3311				MaxVersion: VersionTLS13,
3312			},
3313			expectUnsolicitedKeyUpdate: true,
3314			flags:                      []string{"-key-update"},
3315		},
3316		{
3317			testType: serverTest,
3318			name:     "KeyUpdate-FromServer",
3319			config: Config{
3320				MaxVersion: VersionTLS13,
3321			},
3322			expectUnsolicitedKeyUpdate: true,
3323			flags:                      []string{"-key-update"},
3324		},
3325		{
3326			name: "KeyUpdate-InvalidRequestMode",
3327			config: Config{
3328				MaxVersion: VersionTLS13,
3329			},
3330			sendKeyUpdates:   1,
3331			keyUpdateRequest: 42,
3332			shouldFail:       true,
3333			expectedError:    ":DECODE_ERROR:",
3334		},
3335		{
3336			// Test that KeyUpdates are acknowledged properly.
3337			name: "KeyUpdate-RequestACK",
3338			config: Config{
3339				MaxVersion: VersionTLS13,
3340				Bugs: ProtocolBugs{
3341					RejectUnsolicitedKeyUpdate: true,
3342				},
3343			},
3344			// Test the shim receiving many KeyUpdates in a row.
3345			sendKeyUpdates:   5,
3346			messageCount:     5,
3347			keyUpdateRequest: keyUpdateRequested,
3348		},
3349		{
3350			// Test that KeyUpdates are acknowledged properly if the
3351			// peer's KeyUpdate is discovered while a write is
3352			// pending.
3353			name: "KeyUpdate-RequestACK-UnfinishedWrite",
3354			config: Config{
3355				MaxVersion: VersionTLS13,
3356				Bugs: ProtocolBugs{
3357					RejectUnsolicitedKeyUpdate: true,
3358				},
3359			},
3360			// Test the shim receiving many KeyUpdates in a row.
3361			sendKeyUpdates:          5,
3362			messageCount:            5,
3363			keyUpdateRequest:        keyUpdateRequested,
3364			readWithUnfinishedWrite: true,
3365			flags:                   []string{"-async"},
3366		},
3367		{
3368			name: "SendSNIWarningAlert",
3369			config: Config{
3370				MaxVersion: VersionTLS12,
3371				Bugs: ProtocolBugs{
3372					SendSNIWarningAlert: true,
3373				},
3374			},
3375		},
3376		{
3377			testType: serverTest,
3378			name:     "ExtraCompressionMethods-TLS12",
3379			config: Config{
3380				MaxVersion: VersionTLS12,
3381				Bugs: ProtocolBugs{
3382					SendCompressionMethods: []byte{1, 2, 3, compressionNone, 4, 5, 6},
3383				},
3384			},
3385		},
3386		{
3387			testType: serverTest,
3388			name:     "ExtraCompressionMethods-TLS13",
3389			config: Config{
3390				MaxVersion: VersionTLS13,
3391				Bugs: ProtocolBugs{
3392					SendCompressionMethods: []byte{1, 2, 3, compressionNone, 4, 5, 6},
3393				},
3394			},
3395			shouldFail:         true,
3396			expectedError:      ":INVALID_COMPRESSION_LIST:",
3397			expectedLocalError: "remote error: illegal parameter",
3398		},
3399		{
3400			testType: serverTest,
3401			name:     "NoNullCompression-TLS12",
3402			config: Config{
3403				MaxVersion: VersionTLS12,
3404				Bugs: ProtocolBugs{
3405					SendCompressionMethods: []byte{1, 2, 3, 4, 5, 6},
3406				},
3407			},
3408			shouldFail:         true,
3409			expectedError:      ":INVALID_COMPRESSION_LIST:",
3410			expectedLocalError: "remote error: illegal parameter",
3411		},
3412		{
3413			testType: serverTest,
3414			name:     "NoNullCompression-TLS13",
3415			config: Config{
3416				MaxVersion: VersionTLS13,
3417				Bugs: ProtocolBugs{
3418					SendCompressionMethods: []byte{1, 2, 3, 4, 5, 6},
3419				},
3420			},
3421			shouldFail:         true,
3422			expectedError:      ":INVALID_COMPRESSION_LIST:",
3423			expectedLocalError: "remote error: illegal parameter",
3424		},
3425		// Test that the client rejects invalid compression methods
3426		// from the server.
3427		{
3428			testType: clientTest,
3429			name:     "InvalidCompressionMethod",
3430			config: Config{
3431				MaxVersion: VersionTLS12,
3432				Bugs: ProtocolBugs{
3433					SendCompressionMethod: 1,
3434				},
3435			},
3436			shouldFail:         true,
3437			expectedError:      ":UNSUPPORTED_COMPRESSION_ALGORITHM:",
3438			expectedLocalError: "remote error: illegal parameter",
3439		},
3440		{
3441			testType: clientTest,
3442			name:     "TLS13-InvalidCompressionMethod",
3443			config: Config{
3444				MaxVersion: VersionTLS13,
3445				Bugs: ProtocolBugs{
3446					SendCompressionMethod: 1,
3447				},
3448			},
3449			shouldFail:    true,
3450			expectedError: ":DECODE_ERROR:",
3451		},
3452		{
3453			testType: clientTest,
3454			name:     "TLS13-HRR-InvalidCompressionMethod",
3455			config: Config{
3456				MaxVersion:       VersionTLS13,
3457				CurvePreferences: []CurveID{CurveP384},
3458				Bugs: ProtocolBugs{
3459					SendCompressionMethod: 1,
3460				},
3461			},
3462			shouldFail:         true,
3463			expectedError:      ":DECODE_ERROR:",
3464			expectedLocalError: "remote error: error decoding message",
3465		},
3466		{
3467			name: "GREASE-Client-TLS12",
3468			config: Config{
3469				MaxVersion: VersionTLS12,
3470				Bugs: ProtocolBugs{
3471					ExpectGREASE: true,
3472				},
3473			},
3474			flags: []string{"-enable-grease"},
3475		},
3476		{
3477			name: "GREASE-Client-TLS13",
3478			config: Config{
3479				MaxVersion: VersionTLS13,
3480				Bugs: ProtocolBugs{
3481					ExpectGREASE: true,
3482				},
3483			},
3484			flags: []string{"-enable-grease"},
3485		},
3486		{
3487			testType: serverTest,
3488			name:     "GREASE-Server-TLS13",
3489			config: Config{
3490				MaxVersion: VersionTLS13,
3491				Bugs: ProtocolBugs{
3492					// TLS 1.3 servers are expected to
3493					// always enable GREASE. TLS 1.3 is new,
3494					// so there is no existing ecosystem to
3495					// worry about.
3496					ExpectGREASE: true,
3497				},
3498			},
3499		},
3500		{
3501			// Test the TLS 1.2 server so there is a large
3502			// unencrypted certificate as well as application data.
3503			testType: serverTest,
3504			name:     "MaxSendFragment-TLS12",
3505			config: Config{
3506				MaxVersion: VersionTLS12,
3507				Bugs: ProtocolBugs{
3508					MaxReceivePlaintext: 512,
3509				},
3510			},
3511			messageLen: 1024,
3512			flags: []string{
3513				"-max-send-fragment", "512",
3514				"-read-size", "1024",
3515			},
3516		},
3517		{
3518			// Test the TLS 1.2 server so there is a large
3519			// unencrypted certificate as well as application data.
3520			testType: serverTest,
3521			name:     "MaxSendFragment-TLS12-TooLarge",
3522			config: Config{
3523				MaxVersion: VersionTLS12,
3524				Bugs: ProtocolBugs{
3525					// Ensure that some of the records are
3526					// 512.
3527					MaxReceivePlaintext: 511,
3528				},
3529			},
3530			messageLen: 1024,
3531			flags: []string{
3532				"-max-send-fragment", "512",
3533				"-read-size", "1024",
3534			},
3535			shouldFail:         true,
3536			expectedLocalError: "local error: record overflow",
3537		},
3538		{
3539			// Test the TLS 1.3 server so there is a large encrypted
3540			// certificate as well as application data.
3541			testType: serverTest,
3542			name:     "MaxSendFragment-TLS13",
3543			config: Config{
3544				MaxVersion: VersionTLS13,
3545				Bugs: ProtocolBugs{
3546					MaxReceivePlaintext:            512,
3547					ExpectPackedEncryptedHandshake: 512,
3548				},
3549			},
3550			messageLen: 1024,
3551			flags: []string{
3552				"-max-send-fragment", "512",
3553				"-read-size", "1024",
3554			},
3555		},
3556		{
3557			// Test the TLS 1.3 server so there is a large encrypted
3558			// certificate as well as application data.
3559			testType: serverTest,
3560			name:     "MaxSendFragment-TLS13-TooLarge",
3561			config: Config{
3562				MaxVersion: VersionTLS13,
3563				Bugs: ProtocolBugs{
3564					// Ensure that some of the records are
3565					// 512.
3566					MaxReceivePlaintext: 511,
3567				},
3568			},
3569			messageLen: 1024,
3570			flags: []string{
3571				"-max-send-fragment", "512",
3572				"-read-size", "1024",
3573			},
3574			shouldFail:         true,
3575			expectedLocalError: "local error: record overflow",
3576		},
3577		{
3578			// Test that handshake data is tightly packed in TLS 1.3.
3579			testType: serverTest,
3580			name:     "PackedEncryptedHandshake-TLS13",
3581			config: Config{
3582				MaxVersion: VersionTLS13,
3583				Bugs: ProtocolBugs{
3584					ExpectPackedEncryptedHandshake: 16384,
3585				},
3586			},
3587		},
3588		{
3589			// Test that DTLS can handle multiple application data
3590			// records in a single packet.
3591			protocol: dtls,
3592			name:     "SplitAndPackAppData-DTLS",
3593			config: Config{
3594				Bugs: ProtocolBugs{
3595					SplitAndPackAppData: true,
3596				},
3597			},
3598		},
3599		{
3600			protocol: dtls,
3601			name:     "SplitAndPackAppData-DTLS-Async",
3602			config: Config{
3603				Bugs: ProtocolBugs{
3604					SplitAndPackAppData: true,
3605				},
3606			},
3607			flags: []string{"-async"},
3608		},
3609		{
3610			// DTLS 1.2 allows up to a 255-byte HelloVerifyRequest cookie, which
3611			// is the largest encodable value.
3612			protocol: dtls,
3613			name:     "DTLS-HelloVerifyRequest-255",
3614			config: Config{
3615				MaxVersion: VersionTLS12,
3616				Bugs: ProtocolBugs{
3617					HelloVerifyRequestCookieLength: 255,
3618				},
3619			},
3620		},
3621		{
3622			// DTLS 1.2 allows up to a 0-byte HelloVerifyRequest cookie, which
3623			// was probably a mistake in the spec but test that it works
3624			// nonetheless.
3625			protocol: dtls,
3626			name:     "DTLS-HelloVerifyRequest-0",
3627			config: Config{
3628				MaxVersion: VersionTLS12,
3629				Bugs: ProtocolBugs{
3630					EmptyHelloVerifyRequestCookie: true,
3631				},
3632			},
3633		},
3634	}
3635	testCases = append(testCases, basicTests...)
3636
3637	// Test that very large messages can be received.
3638	cert := rsaCertificate
3639	for i := 0; i < 50; i++ {
3640		cert.Certificate = append(cert.Certificate, cert.Certificate[0])
3641	}
3642	testCases = append(testCases, testCase{
3643		name: "LargeMessage",
3644		config: Config{
3645			Credential: &cert,
3646		},
3647	})
3648	testCases = append(testCases, testCase{
3649		protocol: dtls,
3650		name:     "LargeMessage-DTLS",
3651		config: Config{
3652			Credential: &cert,
3653		},
3654	})
3655
3656	// They are rejected if the maximum certificate chain length is capped.
3657	testCases = append(testCases, testCase{
3658		name: "LargeMessage-Reject",
3659		config: Config{
3660			Credential: &cert,
3661		},
3662		flags:         []string{"-max-cert-list", "16384"},
3663		shouldFail:    true,
3664		expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
3665	})
3666	testCases = append(testCases, testCase{
3667		protocol: dtls,
3668		name:     "LargeMessage-Reject-DTLS",
3669		config: Config{
3670			Credential: &cert,
3671		},
3672		flags:         []string{"-max-cert-list", "16384"},
3673		shouldFail:    true,
3674		expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
3675	})
3676
3677	// Servers echoing the TLS 1.3 compatibility mode session ID should be
3678	// rejected.
3679	testCases = append(testCases, testCase{
3680		name: "EchoTLS13CompatibilitySessionID",
3681		config: Config{
3682			MaxVersion: VersionTLS12,
3683			Bugs: ProtocolBugs{
3684				EchoSessionIDInFullHandshake: true,
3685			},
3686		},
3687		shouldFail:         true,
3688		expectedError:      ":SERVER_ECHOED_INVALID_SESSION_ID:",
3689		expectedLocalError: "remote error: illegal parameter",
3690	})
3691
3692	// Servers should reject QUIC client hellos that have a legacy
3693	// session ID.
3694	testCases = append(testCases, testCase{
3695		name:     "QUICCompatibilityMode",
3696		testType: serverTest,
3697		protocol: quic,
3698		config: Config{
3699			MinVersion: VersionTLS13,
3700			Bugs: ProtocolBugs{
3701				CompatModeWithQUIC: true,
3702			},
3703		},
3704		shouldFail:    true,
3705		expectedError: ":UNEXPECTED_COMPATIBILITY_MODE:",
3706	})
3707}
3708
3709func addTestForCipherSuite(suite testCipherSuite, ver tlsVersion, protocol protocol) {
3710	const psk = "12345"
3711	const pskIdentity = "luggage combo"
3712
3713	if !ver.supportsProtocol(protocol) {
3714		return
3715	}
3716	prefix := protocol.String() + "-"
3717
3718	var cert *Credential
3719	if isTLS13Suite(suite.name) {
3720		cert = &rsaCertificate
3721	} else if hasComponent(suite.name, "ECDSA") {
3722		cert = &ecdsaP256Certificate
3723	} else if hasComponent(suite.name, "RSA") {
3724		cert = &rsaCertificate
3725	}
3726
3727	var flags []string
3728	if hasComponent(suite.name, "PSK") {
3729		flags = append(flags,
3730			"-psk", psk,
3731			"-psk-identity", pskIdentity)
3732	}
3733
3734	if hasComponent(suite.name, "3DES") {
3735		// BoringSSL disables 3DES ciphers by default.
3736		flags = append(flags, "-cipher", "3DES")
3737	}
3738
3739	var shouldFail bool
3740	if isTLS12Only(suite.name) && ver.version < VersionTLS12 {
3741		shouldFail = true
3742	}
3743	if !isTLS13Suite(suite.name) && ver.version >= VersionTLS13 {
3744		shouldFail = true
3745	}
3746	if isTLS13Suite(suite.name) && ver.version < VersionTLS13 {
3747		shouldFail = true
3748	}
3749
3750	var sendCipherSuite uint16
3751	var expectedServerError, expectedClientError string
3752	serverCipherSuites := []uint16{suite.id}
3753	if shouldFail {
3754		expectedServerError = ":NO_SHARED_CIPHER:"
3755		if ver.version >= VersionTLS13 && cert == nil {
3756			// TLS 1.2 PSK ciphers won't configure a server certificate, but we
3757			// require one in TLS 1.3.
3758			expectedServerError = ":NO_CERTIFICATE_SET:"
3759		}
3760		expectedClientError = ":WRONG_CIPHER_RETURNED:"
3761		// Configure the server to select ciphers as normal but
3762		// select an incompatible cipher in ServerHello.
3763		serverCipherSuites = nil
3764		sendCipherSuite = suite.id
3765	}
3766
3767	// Verify exporters interoperate.
3768	exportKeyingMaterial := 1024
3769
3770	testCases = append(testCases, testCase{
3771		testType: serverTest,
3772		protocol: protocol,
3773		name:     prefix + ver.name + "-" + suite.name + "-server",
3774		config: Config{
3775			MinVersion:           ver.version,
3776			MaxVersion:           ver.version,
3777			CipherSuites:         []uint16{suite.id},
3778			Credential:           cert,
3779			PreSharedKey:         []byte(psk),
3780			PreSharedKeyIdentity: pskIdentity,
3781			Bugs: ProtocolBugs{
3782				AdvertiseAllConfiguredCiphers: true,
3783			},
3784		},
3785		shimCertificate:      cert,
3786		flags:                flags,
3787		resumeSession:        true,
3788		shouldFail:           shouldFail,
3789		expectedError:        expectedServerError,
3790		exportKeyingMaterial: exportKeyingMaterial,
3791	})
3792
3793	testCases = append(testCases, testCase{
3794		testType: clientTest,
3795		protocol: protocol,
3796		name:     prefix + ver.name + "-" + suite.name + "-client",
3797		config: Config{
3798			MinVersion:           ver.version,
3799			MaxVersion:           ver.version,
3800			CipherSuites:         serverCipherSuites,
3801			Credential:           cert,
3802			PreSharedKey:         []byte(psk),
3803			PreSharedKeyIdentity: pskIdentity,
3804			Bugs: ProtocolBugs{
3805				IgnorePeerCipherPreferences: shouldFail,
3806				SendCipherSuite:             sendCipherSuite,
3807			},
3808		},
3809		flags:                flags,
3810		resumeSession:        true,
3811		shouldFail:           shouldFail,
3812		expectedError:        expectedClientError,
3813		exportKeyingMaterial: exportKeyingMaterial,
3814	})
3815
3816	if shouldFail {
3817		return
3818	}
3819
3820	// Ensure the maximum record size is accepted.
3821	testCases = append(testCases, testCase{
3822		protocol: protocol,
3823		name:     prefix + ver.name + "-" + suite.name + "-LargeRecord",
3824		config: Config{
3825			MinVersion:           ver.version,
3826			MaxVersion:           ver.version,
3827			CipherSuites:         []uint16{suite.id},
3828			Credential:           cert,
3829			PreSharedKey:         []byte(psk),
3830			PreSharedKeyIdentity: pskIdentity,
3831		},
3832		flags:      flags,
3833		messageLen: maxPlaintext,
3834	})
3835
3836	// Test bad records for all ciphers. Bad records are fatal in TLS
3837	// and ignored in DTLS.
3838	shouldFail = protocol == tls
3839	var expectedError string
3840	if shouldFail {
3841		expectedError = ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:"
3842	}
3843
3844	// When QUIC is used, the QUIC stack handles record encryption/decryption.
3845	// Thus it is not possible for the TLS stack in QUIC mode to receive a
3846	// bad record (i.e. one that fails to decrypt).
3847	if protocol != quic {
3848		testCases = append(testCases, testCase{
3849			protocol: protocol,
3850			name:     prefix + ver.name + "-" + suite.name + "-BadRecord",
3851			config: Config{
3852				MinVersion:           ver.version,
3853				MaxVersion:           ver.version,
3854				CipherSuites:         []uint16{suite.id},
3855				Credential:           cert,
3856				PreSharedKey:         []byte(psk),
3857				PreSharedKeyIdentity: pskIdentity,
3858			},
3859			flags:            flags,
3860			damageFirstWrite: true,
3861			messageLen:       maxPlaintext,
3862			shouldFail:       shouldFail,
3863			expectedError:    expectedError,
3864		})
3865	}
3866}
3867
3868func addCipherSuiteTests() {
3869	const bogusCipher = 0xfe00
3870
3871	for _, suite := range testCipherSuites {
3872		for _, ver := range tlsVersions {
3873			for _, protocol := range []protocol{tls, dtls, quic} {
3874				addTestForCipherSuite(suite, ver, protocol)
3875			}
3876		}
3877	}
3878
3879	testCases = append(testCases, testCase{
3880		name: "NoSharedCipher",
3881		config: Config{
3882			MaxVersion:   VersionTLS12,
3883			CipherSuites: []uint16{},
3884		},
3885		shouldFail:    true,
3886		expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
3887	})
3888
3889	testCases = append(testCases, testCase{
3890		name: "NoSharedCipher-TLS13",
3891		config: Config{
3892			MaxVersion:   VersionTLS13,
3893			CipherSuites: []uint16{},
3894		},
3895		shouldFail:    true,
3896		expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
3897	})
3898
3899	testCases = append(testCases, testCase{
3900		name: "UnsupportedCipherSuite",
3901		config: Config{
3902			MaxVersion:   VersionTLS12,
3903			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
3904			Bugs: ProtocolBugs{
3905				IgnorePeerCipherPreferences: true,
3906			},
3907		},
3908		flags:         []string{"-cipher", "DEFAULT:!AES"},
3909		shouldFail:    true,
3910		expectedError: ":WRONG_CIPHER_RETURNED:",
3911	})
3912
3913	testCases = append(testCases, testCase{
3914		name: "ServerHelloBogusCipher",
3915		config: Config{
3916			MaxVersion: VersionTLS12,
3917			Bugs: ProtocolBugs{
3918				SendCipherSuite: bogusCipher,
3919			},
3920		},
3921		shouldFail:    true,
3922		expectedError: ":WRONG_CIPHER_RETURNED:",
3923	})
3924	testCases = append(testCases, testCase{
3925		name: "ServerHelloBogusCipher-TLS13",
3926		config: Config{
3927			MaxVersion: VersionTLS13,
3928			Bugs: ProtocolBugs{
3929				SendCipherSuite: bogusCipher,
3930			},
3931		},
3932		shouldFail:    true,
3933		expectedError: ":WRONG_CIPHER_RETURNED:",
3934	})
3935
3936	// The server must be tolerant to bogus ciphers.
3937	testCases = append(testCases, testCase{
3938		testType: serverTest,
3939		name:     "UnknownCipher",
3940		config: Config{
3941			MaxVersion:   VersionTLS12,
3942			CipherSuites: []uint16{bogusCipher, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3943			Bugs: ProtocolBugs{
3944				AdvertiseAllConfiguredCiphers: true,
3945			},
3946		},
3947	})
3948
3949	// The server must be tolerant to bogus ciphers.
3950	testCases = append(testCases, testCase{
3951		testType: serverTest,
3952		name:     "UnknownCipher-TLS13",
3953		config: Config{
3954			MaxVersion:   VersionTLS13,
3955			CipherSuites: []uint16{bogusCipher, TLS_AES_128_GCM_SHA256},
3956			Bugs: ProtocolBugs{
3957				AdvertiseAllConfiguredCiphers: true,
3958			},
3959		},
3960	})
3961
3962	// Test empty ECDHE_PSK identity hints work as expected.
3963	testCases = append(testCases, testCase{
3964		name: "EmptyECDHEPSKHint",
3965		config: Config{
3966			MaxVersion:   VersionTLS12,
3967			CipherSuites: []uint16{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
3968			PreSharedKey: []byte("secret"),
3969		},
3970		flags: []string{"-psk", "secret"},
3971	})
3972
3973	// Test empty PSK identity hints work as expected, even if an explicit
3974	// ServerKeyExchange is sent.
3975	testCases = append(testCases, testCase{
3976		name: "ExplicitEmptyPSKHint",
3977		config: Config{
3978			MaxVersion:   VersionTLS12,
3979			CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
3980			PreSharedKey: []byte("secret"),
3981			Bugs: ProtocolBugs{
3982				AlwaysSendPreSharedKeyIdentityHint: true,
3983			},
3984		},
3985		flags: []string{"-psk", "secret"},
3986	})
3987
3988	// Test that clients enforce that the server-sent certificate and cipher
3989	// suite match in TLS 1.2.
3990	testCases = append(testCases, testCase{
3991		name: "CertificateCipherMismatch-RSA",
3992		config: Config{
3993			MaxVersion:   VersionTLS12,
3994			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
3995			Credential:   &rsaCertificate,
3996			Bugs: ProtocolBugs{
3997				SendCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
3998			},
3999		},
4000		shouldFail:    true,
4001		expectedError: ":WRONG_CERTIFICATE_TYPE:",
4002	})
4003	testCases = append(testCases, testCase{
4004		name: "CertificateCipherMismatch-ECDSA",
4005		config: Config{
4006			MaxVersion:   VersionTLS12,
4007			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
4008			Credential:   &ecdsaP256Certificate,
4009			Bugs: ProtocolBugs{
4010				SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
4011			},
4012		},
4013		shouldFail:    true,
4014		expectedError: ":WRONG_CERTIFICATE_TYPE:",
4015	})
4016	testCases = append(testCases, testCase{
4017		name: "CertificateCipherMismatch-Ed25519",
4018		config: Config{
4019			MaxVersion:   VersionTLS12,
4020			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
4021			Credential:   &ed25519Certificate,
4022			Bugs: ProtocolBugs{
4023				SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
4024			},
4025		},
4026		shouldFail:    true,
4027		expectedError: ":WRONG_CERTIFICATE_TYPE:",
4028	})
4029
4030	// Test that servers decline to select a cipher suite which is
4031	// inconsistent with their configured certificate.
4032	testCases = append(testCases, testCase{
4033		testType: serverTest,
4034		name:     "ServerCipherFilter-RSA",
4035		config: Config{
4036			MaxVersion:   VersionTLS12,
4037			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
4038		},
4039		shimCertificate: &rsaCertificate,
4040		shouldFail:      true,
4041		expectedError:   ":NO_SHARED_CIPHER:",
4042	})
4043	testCases = append(testCases, testCase{
4044		testType: serverTest,
4045		name:     "ServerCipherFilter-ECDSA",
4046		config: Config{
4047			MaxVersion:   VersionTLS12,
4048			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4049		},
4050		shimCertificate: &ecdsaP256Certificate,
4051		shouldFail:      true,
4052		expectedError:   ":NO_SHARED_CIPHER:",
4053	})
4054	testCases = append(testCases, testCase{
4055		testType: serverTest,
4056		name:     "ServerCipherFilter-Ed25519",
4057		config: Config{
4058			MaxVersion:   VersionTLS12,
4059			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
4060		},
4061		shimCertificate: &ed25519Certificate,
4062		shouldFail:      true,
4063		expectedError:   ":NO_SHARED_CIPHER:",
4064	})
4065
4066	// Test cipher suite negotiation works as expected. Configure a
4067	// complicated cipher suite configuration.
4068	const negotiationTestCiphers = "" +
4069		"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:" +
4070		"[TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384|TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256|TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA]:" +
4071		"TLS_RSA_WITH_AES_128_GCM_SHA256:" +
4072		"TLS_RSA_WITH_AES_128_CBC_SHA:" +
4073		"[TLS_RSA_WITH_AES_256_GCM_SHA384|TLS_RSA_WITH_AES_256_CBC_SHA]"
4074	negotiationTests := []struct {
4075		ciphers  []uint16
4076		expected uint16
4077	}{
4078		// Server preferences are honored, including when
4079		// equipreference groups are involved.
4080		{
4081			[]uint16{
4082				TLS_RSA_WITH_AES_256_GCM_SHA384,
4083				TLS_RSA_WITH_AES_128_CBC_SHA,
4084				TLS_RSA_WITH_AES_128_GCM_SHA256,
4085				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
4086				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
4087			},
4088			TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
4089		},
4090		{
4091			[]uint16{
4092				TLS_RSA_WITH_AES_256_GCM_SHA384,
4093				TLS_RSA_WITH_AES_128_CBC_SHA,
4094				TLS_RSA_WITH_AES_128_GCM_SHA256,
4095				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
4096			},
4097			TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
4098		},
4099		{
4100			[]uint16{
4101				TLS_RSA_WITH_AES_256_GCM_SHA384,
4102				TLS_RSA_WITH_AES_128_CBC_SHA,
4103				TLS_RSA_WITH_AES_128_GCM_SHA256,
4104			},
4105			TLS_RSA_WITH_AES_128_GCM_SHA256,
4106		},
4107		{
4108			[]uint16{
4109				TLS_RSA_WITH_AES_256_GCM_SHA384,
4110				TLS_RSA_WITH_AES_128_CBC_SHA,
4111			},
4112			TLS_RSA_WITH_AES_128_CBC_SHA,
4113		},
4114		// Equipreference groups use the client preference.
4115		{
4116			[]uint16{
4117				TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
4118				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
4119				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
4120			},
4121			TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
4122		},
4123		{
4124			[]uint16{
4125				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
4126				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
4127			},
4128			TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
4129		},
4130		{
4131			[]uint16{
4132				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
4133				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
4134			},
4135			TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
4136		},
4137		{
4138			[]uint16{
4139				TLS_RSA_WITH_AES_256_GCM_SHA384,
4140				TLS_RSA_WITH_AES_256_CBC_SHA,
4141			},
4142			TLS_RSA_WITH_AES_256_GCM_SHA384,
4143		},
4144		{
4145			[]uint16{
4146				TLS_RSA_WITH_AES_256_CBC_SHA,
4147				TLS_RSA_WITH_AES_256_GCM_SHA384,
4148			},
4149			TLS_RSA_WITH_AES_256_CBC_SHA,
4150		},
4151		// If there are two equipreference groups, the preferred one
4152		// takes precedence.
4153		{
4154			[]uint16{
4155				TLS_RSA_WITH_AES_256_GCM_SHA384,
4156				TLS_RSA_WITH_AES_256_CBC_SHA,
4157				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
4158				TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
4159			},
4160			TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
4161		},
4162	}
4163	for i, t := range negotiationTests {
4164		testCases = append(testCases, testCase{
4165			testType: serverTest,
4166			name:     "CipherNegotiation-" + strconv.Itoa(i),
4167			config: Config{
4168				MaxVersion:   VersionTLS12,
4169				CipherSuites: t.ciphers,
4170			},
4171			flags: []string{"-cipher", negotiationTestCiphers},
4172			expectations: connectionExpectations{
4173				cipher: t.expected,
4174			},
4175		})
4176	}
4177}
4178
4179func addBadECDSASignatureTests() {
4180	for badR := BadValue(1); badR < NumBadValues; badR++ {
4181		for badS := BadValue(1); badS < NumBadValues; badS++ {
4182			testCases = append(testCases, testCase{
4183				name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
4184				config: Config{
4185					MaxVersion:   VersionTLS12,
4186					CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
4187					Credential:   &ecdsaP256Certificate,
4188					Bugs: ProtocolBugs{
4189						BadECDSAR: badR,
4190						BadECDSAS: badS,
4191					},
4192				},
4193				shouldFail:    true,
4194				expectedError: ":BAD_SIGNATURE:",
4195			})
4196			testCases = append(testCases, testCase{
4197				name: fmt.Sprintf("BadECDSA-%d-%d-TLS13", badR, badS),
4198				config: Config{
4199					MaxVersion: VersionTLS13,
4200					Credential: &ecdsaP256Certificate,
4201					Bugs: ProtocolBugs{
4202						BadECDSAR: badR,
4203						BadECDSAS: badS,
4204					},
4205				},
4206				shouldFail:    true,
4207				expectedError: ":BAD_SIGNATURE:",
4208			})
4209		}
4210	}
4211}
4212
4213func addCBCPaddingTests() {
4214	testCases = append(testCases, testCase{
4215		name: "MaxCBCPadding",
4216		config: Config{
4217			MaxVersion:   VersionTLS12,
4218			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
4219			Bugs: ProtocolBugs{
4220				MaxPadding: true,
4221			},
4222		},
4223		messageLen: 12, // 20 bytes of SHA-1 + 12 == 0 % block size
4224	})
4225	testCases = append(testCases, testCase{
4226		name: "BadCBCPadding",
4227		config: Config{
4228			MaxVersion:   VersionTLS12,
4229			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
4230			Bugs: ProtocolBugs{
4231				PaddingFirstByteBad: true,
4232			},
4233		},
4234		shouldFail:    true,
4235		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
4236	})
4237	// OpenSSL previously had an issue where the first byte of padding in
4238	// 255 bytes of padding wasn't checked.
4239	testCases = append(testCases, testCase{
4240		name: "BadCBCPadding255",
4241		config: Config{
4242			MaxVersion:   VersionTLS12,
4243			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
4244			Bugs: ProtocolBugs{
4245				MaxPadding:               true,
4246				PaddingFirstByteBadIf255: true,
4247			},
4248		},
4249		messageLen:    12, // 20 bytes of SHA-1 + 12 == 0 % block size
4250		shouldFail:    true,
4251		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
4252	})
4253}
4254
4255func addCBCSplittingTests() {
4256	var cbcCiphers = []struct {
4257		name   string
4258		cipher uint16
4259	}{
4260		{"3DES", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
4261		{"AES128", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
4262		{"AES256", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
4263	}
4264	for _, t := range cbcCiphers {
4265		testCases = append(testCases, testCase{
4266			name: "CBCRecordSplitting-" + t.name,
4267			config: Config{
4268				MaxVersion:   VersionTLS10,
4269				MinVersion:   VersionTLS10,
4270				CipherSuites: []uint16{t.cipher},
4271				Bugs: ProtocolBugs{
4272					ExpectRecordSplitting: true,
4273				},
4274			},
4275			messageLen:    -1, // read until EOF
4276			resumeSession: true,
4277			flags: []string{
4278				"-async",
4279				"-write-different-record-sizes",
4280				"-cbc-record-splitting",
4281				// BoringSSL disables 3DES by default.
4282				"-cipher", "ALL:3DES",
4283			},
4284		})
4285		testCases = append(testCases, testCase{
4286			name: "CBCRecordSplittingPartialWrite-" + t.name,
4287			config: Config{
4288				MaxVersion:   VersionTLS10,
4289				MinVersion:   VersionTLS10,
4290				CipherSuites: []uint16{t.cipher},
4291				Bugs: ProtocolBugs{
4292					ExpectRecordSplitting: true,
4293				},
4294			},
4295			messageLen: -1, // read until EOF
4296			flags: []string{
4297				"-async",
4298				"-write-different-record-sizes",
4299				"-cbc-record-splitting",
4300				"-partial-write",
4301				// BoringSSL disables 3DES by default.
4302				"-cipher", "ALL:3DES",
4303			},
4304		})
4305	}
4306}
4307
4308func addClientAuthTests() {
4309	// Add a dummy cert pool to stress certificate authority parsing.
4310	certPool := x509.NewCertPool()
4311	for _, cert := range []Credential{rsaCertificate, rsa1024Certificate} {
4312		cert, err := x509.ParseCertificate(cert.Certificate[0])
4313		if err != nil {
4314			panic(err)
4315		}
4316		certPool.AddCert(cert)
4317	}
4318	caNames := certPool.Subjects()
4319
4320	for _, ver := range tlsVersions {
4321		testCases = append(testCases, testCase{
4322			testType: clientTest,
4323			name:     ver.name + "-Client-ClientAuth-RSA",
4324			config: Config{
4325				MinVersion: ver.version,
4326				MaxVersion: ver.version,
4327				ClientAuth: RequireAnyClientCert,
4328				ClientCAs:  certPool,
4329			},
4330			shimCertificate: &rsaCertificate,
4331		})
4332		testCases = append(testCases, testCase{
4333			testType: serverTest,
4334			name:     ver.name + "-Server-ClientAuth-RSA",
4335			config: Config{
4336				MinVersion: ver.version,
4337				MaxVersion: ver.version,
4338				Credential: &rsaCertificate,
4339			},
4340			flags: []string{"-require-any-client-certificate"},
4341		})
4342		testCases = append(testCases, testCase{
4343			testType: serverTest,
4344			name:     ver.name + "-Server-ClientAuth-ECDSA",
4345			config: Config{
4346				MinVersion: ver.version,
4347				MaxVersion: ver.version,
4348				Credential: &ecdsaP256Certificate,
4349			},
4350			flags: []string{"-require-any-client-certificate"},
4351		})
4352		testCases = append(testCases, testCase{
4353			testType: clientTest,
4354			name:     ver.name + "-Client-ClientAuth-ECDSA",
4355			config: Config{
4356				MinVersion: ver.version,
4357				MaxVersion: ver.version,
4358				ClientAuth: RequireAnyClientCert,
4359				ClientCAs:  certPool,
4360			},
4361			shimCertificate: &ecdsaP256Certificate,
4362		})
4363
4364		testCases = append(testCases, testCase{
4365			name: "NoClientCertificate-" + ver.name,
4366			config: Config{
4367				MinVersion: ver.version,
4368				MaxVersion: ver.version,
4369				ClientAuth: RequireAnyClientCert,
4370			},
4371			shouldFail:         true,
4372			expectedLocalError: "client didn't provide a certificate",
4373		})
4374
4375		testCases = append(testCases, testCase{
4376			// Even if not configured to expect a certificate, OpenSSL will
4377			// return X509_V_OK as the verify_result.
4378			testType: serverTest,
4379			name:     "NoClientCertificateRequested-Server-" + ver.name,
4380			config: Config{
4381				MinVersion: ver.version,
4382				MaxVersion: ver.version,
4383			},
4384			flags: []string{
4385				"-expect-verify-result",
4386			},
4387			resumeSession: true,
4388		})
4389
4390		testCases = append(testCases, testCase{
4391			// If a client certificate is not provided, OpenSSL will still
4392			// return X509_V_OK as the verify_result.
4393			testType: serverTest,
4394			name:     "NoClientCertificate-Server-" + ver.name,
4395			config: Config{
4396				MinVersion: ver.version,
4397				MaxVersion: ver.version,
4398			},
4399			flags: []string{
4400				"-expect-verify-result",
4401				"-verify-peer",
4402			},
4403			resumeSession: true,
4404		})
4405
4406		certificateRequired := "remote error: certificate required"
4407		if ver.version < VersionTLS13 {
4408			// Prior to TLS 1.3, the generic handshake_failure alert
4409			// was used.
4410			certificateRequired = "remote error: handshake failure"
4411		}
4412		testCases = append(testCases, testCase{
4413			testType: serverTest,
4414			name:     "RequireAnyClientCertificate-" + ver.name,
4415			config: Config{
4416				MinVersion: ver.version,
4417				MaxVersion: ver.version,
4418			},
4419			flags:              []string{"-require-any-client-certificate"},
4420			shouldFail:         true,
4421			expectedError:      ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
4422			expectedLocalError: certificateRequired,
4423		})
4424
4425		testCases = append(testCases, testCase{
4426			testType: serverTest,
4427			name:     "SkipClientCertificate-" + ver.name,
4428			config: Config{
4429				MinVersion: ver.version,
4430				MaxVersion: ver.version,
4431				Bugs: ProtocolBugs{
4432					SkipClientCertificate: true,
4433				},
4434			},
4435			// Setting SSL_VERIFY_PEER allows anonymous clients.
4436			flags:         []string{"-verify-peer"},
4437			shouldFail:    true,
4438			expectedError: ":UNEXPECTED_MESSAGE:",
4439		})
4440
4441		testCases = append(testCases, testCase{
4442			testType: serverTest,
4443			name:     "VerifyPeerIfNoOBC-NoChannelID-" + ver.name,
4444			config: Config{
4445				MinVersion: ver.version,
4446				MaxVersion: ver.version,
4447			},
4448			flags: []string{
4449				"-enable-channel-id",
4450				"-verify-peer-if-no-obc",
4451			},
4452			shouldFail:         true,
4453			expectedError:      ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
4454			expectedLocalError: certificateRequired,
4455		})
4456
4457		testCases = append(testCases, testCase{
4458			testType: serverTest,
4459			name:     "VerifyPeerIfNoOBC-ChannelID-" + ver.name,
4460			config: Config{
4461				MinVersion: ver.version,
4462				MaxVersion: ver.version,
4463				ChannelID:  &channelIDKey,
4464			},
4465			expectations: connectionExpectations{
4466				channelID: true,
4467			},
4468			flags: []string{
4469				"-enable-channel-id",
4470				"-verify-peer-if-no-obc",
4471			},
4472		})
4473
4474		testCases = append(testCases, testCase{
4475			testType: serverTest,
4476			name:     ver.name + "-Server-CertReq-CA-List",
4477			config: Config{
4478				MinVersion: ver.version,
4479				MaxVersion: ver.version,
4480				Credential: &rsaCertificate,
4481				Bugs: ProtocolBugs{
4482					ExpectCertificateReqNames: caNames,
4483				},
4484			},
4485			flags: []string{
4486				"-require-any-client-certificate",
4487				"-use-client-ca-list", encodeDERValues(caNames),
4488			},
4489		})
4490
4491		testCases = append(testCases, testCase{
4492			testType: clientTest,
4493			name:     ver.name + "-Client-CertReq-CA-List",
4494			config: Config{
4495				MinVersion: ver.version,
4496				MaxVersion: ver.version,
4497				Credential: &rsaCertificate,
4498				ClientAuth: RequireAnyClientCert,
4499				ClientCAs:  certPool,
4500			},
4501			shimCertificate: &rsaCertificate,
4502			flags: []string{
4503				"-expect-client-ca-list", encodeDERValues(caNames),
4504			},
4505		})
4506	}
4507
4508	// Client auth is only legal in certificate-based ciphers.
4509	testCases = append(testCases, testCase{
4510		testType: clientTest,
4511		name:     "ClientAuth-PSK",
4512		config: Config{
4513			MaxVersion:   VersionTLS12,
4514			CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
4515			PreSharedKey: []byte("secret"),
4516			ClientAuth:   RequireAnyClientCert,
4517		},
4518		shimCertificate: &rsaCertificate,
4519		flags: []string{
4520			"-psk", "secret",
4521		},
4522		shouldFail:    true,
4523		expectedError: ":UNEXPECTED_MESSAGE:",
4524	})
4525	testCases = append(testCases, testCase{
4526		testType: clientTest,
4527		name:     "ClientAuth-ECDHE_PSK",
4528		config: Config{
4529			MaxVersion:   VersionTLS12,
4530			CipherSuites: []uint16{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
4531			PreSharedKey: []byte("secret"),
4532			ClientAuth:   RequireAnyClientCert,
4533		},
4534		shimCertificate: &rsaCertificate,
4535		flags: []string{
4536			"-psk", "secret",
4537		},
4538		shouldFail:    true,
4539		expectedError: ":UNEXPECTED_MESSAGE:",
4540	})
4541
4542	// Regression test for a bug where the client CA list, if explicitly
4543	// set to NULL, was mis-encoded.
4544	testCases = append(testCases, testCase{
4545		testType: serverTest,
4546		name:     "Null-Client-CA-List",
4547		config: Config{
4548			MaxVersion: VersionTLS12,
4549			Credential: &rsaCertificate,
4550			Bugs: ProtocolBugs{
4551				ExpectCertificateReqNames: [][]byte{},
4552			},
4553		},
4554		flags: []string{
4555			"-require-any-client-certificate",
4556			"-use-client-ca-list", "<NULL>",
4557		},
4558	})
4559
4560	// Test that an empty client CA list doesn't send a CA extension.
4561	testCases = append(testCases, testCase{
4562		testType: serverTest,
4563		name:     "TLS13-Empty-Client-CA-List",
4564		config: Config{
4565			MaxVersion: VersionTLS13,
4566			Credential: &rsaCertificate,
4567			Bugs: ProtocolBugs{
4568				ExpectNoCertificateAuthoritiesExtension: true,
4569			},
4570		},
4571		flags: []string{
4572			"-require-any-client-certificate",
4573			"-use-client-ca-list", "<EMPTY>",
4574		},
4575	})
4576
4577}
4578
4579func addExtendedMasterSecretTests() {
4580	const expectEMSFlag = "-expect-extended-master-secret"
4581
4582	for _, with := range []bool{false, true} {
4583		prefix := "No"
4584		if with {
4585			prefix = ""
4586		}
4587
4588		for _, isClient := range []bool{false, true} {
4589			suffix := "-Server"
4590			testType := serverTest
4591			if isClient {
4592				suffix = "-Client"
4593				testType = clientTest
4594			}
4595
4596			for _, ver := range tlsVersions {
4597				// In TLS 1.3, the extension is irrelevant and
4598				// always reports as enabled.
4599				var flags []string
4600				if with || ver.version >= VersionTLS13 {
4601					flags = []string{expectEMSFlag}
4602				}
4603
4604				testCases = append(testCases, testCase{
4605					testType: testType,
4606					name:     prefix + "ExtendedMasterSecret-" + ver.name + suffix,
4607					config: Config{
4608						MinVersion: ver.version,
4609						MaxVersion: ver.version,
4610						Bugs: ProtocolBugs{
4611							NoExtendedMasterSecret:      !with,
4612							RequireExtendedMasterSecret: with,
4613						},
4614					},
4615					flags: flags,
4616				})
4617			}
4618		}
4619	}
4620
4621	for _, isClient := range []bool{false, true} {
4622		for _, supportedInFirstConnection := range []bool{false, true} {
4623			for _, supportedInResumeConnection := range []bool{false, true} {
4624				boolToWord := func(b bool) string {
4625					if b {
4626						return "Yes"
4627					}
4628					return "No"
4629				}
4630				suffix := boolToWord(supportedInFirstConnection) + "To" + boolToWord(supportedInResumeConnection) + "-"
4631				if isClient {
4632					suffix += "Client"
4633				} else {
4634					suffix += "Server"
4635				}
4636
4637				supportedConfig := Config{
4638					MaxVersion: VersionTLS12,
4639					Bugs: ProtocolBugs{
4640						RequireExtendedMasterSecret: true,
4641					},
4642				}
4643
4644				noSupportConfig := Config{
4645					MaxVersion: VersionTLS12,
4646					Bugs: ProtocolBugs{
4647						NoExtendedMasterSecret: true,
4648					},
4649				}
4650
4651				test := testCase{
4652					name:          "ExtendedMasterSecret-" + suffix,
4653					resumeSession: true,
4654				}
4655
4656				if !isClient {
4657					test.testType = serverTest
4658				}
4659
4660				if supportedInFirstConnection {
4661					test.config = supportedConfig
4662				} else {
4663					test.config = noSupportConfig
4664				}
4665
4666				if supportedInResumeConnection {
4667					test.resumeConfig = &supportedConfig
4668				} else {
4669					test.resumeConfig = &noSupportConfig
4670				}
4671
4672				switch suffix {
4673				case "YesToYes-Client", "YesToYes-Server":
4674					// When a session is resumed, it should
4675					// still be aware that its master
4676					// secret was generated via EMS and
4677					// thus it's safe to use tls-unique.
4678					test.flags = []string{expectEMSFlag}
4679				case "NoToYes-Server":
4680					// If an original connection did not
4681					// contain EMS, but a resumption
4682					// handshake does, then a server should
4683					// not resume the session.
4684					test.expectResumeRejected = true
4685				case "YesToNo-Server":
4686					// Resuming an EMS session without the
4687					// EMS extension should cause the
4688					// server to abort the connection.
4689					test.shouldFail = true
4690					test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
4691				case "NoToYes-Client":
4692					// A client should abort a connection
4693					// where the server resumed a non-EMS
4694					// session but echoed the EMS
4695					// extension.
4696					test.shouldFail = true
4697					test.expectedError = ":RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION:"
4698				case "YesToNo-Client":
4699					// A client should abort a connection
4700					// where the server didn't echo EMS
4701					// when the session used it.
4702					test.shouldFail = true
4703					test.expectedError = ":RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION:"
4704				}
4705
4706				testCases = append(testCases, test)
4707			}
4708		}
4709	}
4710
4711	// Switching EMS on renegotiation is forbidden.
4712	testCases = append(testCases, testCase{
4713		name: "ExtendedMasterSecret-Renego-NoEMS",
4714		config: Config{
4715			MaxVersion: VersionTLS12,
4716			Bugs: ProtocolBugs{
4717				NoExtendedMasterSecret:                true,
4718				NoExtendedMasterSecretOnRenegotiation: true,
4719			},
4720		},
4721		renegotiate: 1,
4722		flags: []string{
4723			"-renegotiate-freely",
4724			"-expect-total-renegotiations", "1",
4725		},
4726	})
4727
4728	testCases = append(testCases, testCase{
4729		name: "ExtendedMasterSecret-Renego-Upgrade",
4730		config: Config{
4731			MaxVersion: VersionTLS12,
4732			Bugs: ProtocolBugs{
4733				NoExtendedMasterSecret: true,
4734			},
4735		},
4736		renegotiate: 1,
4737		flags: []string{
4738			"-renegotiate-freely",
4739			"-expect-total-renegotiations", "1",
4740		},
4741		shouldFail:    true,
4742		expectedError: ":RENEGOTIATION_EMS_MISMATCH:",
4743	})
4744
4745	testCases = append(testCases, testCase{
4746		name: "ExtendedMasterSecret-Renego-Downgrade",
4747		config: Config{
4748			MaxVersion: VersionTLS12,
4749			Bugs: ProtocolBugs{
4750				NoExtendedMasterSecretOnRenegotiation: true,
4751			},
4752		},
4753		renegotiate: 1,
4754		flags: []string{
4755			"-renegotiate-freely",
4756			"-expect-total-renegotiations", "1",
4757		},
4758		shouldFail:    true,
4759		expectedError: ":RENEGOTIATION_EMS_MISMATCH:",
4760	})
4761}
4762
4763type stateMachineTestConfig struct {
4764	protocol          protocol
4765	async             bool
4766	splitHandshake    bool
4767	packHandshake     bool
4768	implicitHandshake bool
4769}
4770
4771// Adds tests that try to cover the range of the handshake state machine, under
4772// various conditions. Some of these are redundant with other tests, but they
4773// only cover the synchronous case.
4774func addAllStateMachineCoverageTests() {
4775	for _, async := range []bool{false, true} {
4776		for _, protocol := range []protocol{tls, dtls, quic} {
4777			addStateMachineCoverageTests(stateMachineTestConfig{
4778				protocol: protocol,
4779				async:    async,
4780			})
4781			// QUIC doesn't work with the implicit handshake API. Additionally,
4782			// splitting or packing handshake records is meaningless in QUIC.
4783			if protocol != quic {
4784				addStateMachineCoverageTests(stateMachineTestConfig{
4785					protocol:          protocol,
4786					async:             async,
4787					implicitHandshake: true,
4788				})
4789				addStateMachineCoverageTests(stateMachineTestConfig{
4790					protocol:       protocol,
4791					async:          async,
4792					splitHandshake: true,
4793				})
4794				addStateMachineCoverageTests(stateMachineTestConfig{
4795					protocol:      protocol,
4796					async:         async,
4797					packHandshake: true,
4798				})
4799			}
4800		}
4801	}
4802}
4803
4804func addStateMachineCoverageTests(config stateMachineTestConfig) {
4805	var tests []testCase
4806
4807	// Basic handshake, with resumption. Client and server,
4808	// session ID and session ticket.
4809	// The following tests have a max version of 1.2, so they are not suitable
4810	// for use with QUIC.
4811	if config.protocol != quic {
4812		tests = append(tests, testCase{
4813			name: "Basic-Client",
4814			config: Config{
4815				MaxVersion: VersionTLS12,
4816			},
4817			resumeSession: true,
4818			// Ensure session tickets are used, not session IDs.
4819			noSessionCache: true,
4820			flags:          []string{"-expect-no-hrr"},
4821		})
4822		tests = append(tests, testCase{
4823			name: "Basic-Client-RenewTicket",
4824			config: Config{
4825				MaxVersion: VersionTLS12,
4826				Bugs: ProtocolBugs{
4827					RenewTicketOnResume: true,
4828				},
4829			},
4830			flags:                []string{"-expect-ticket-renewal"},
4831			resumeSession:        true,
4832			resumeRenewedSession: true,
4833		})
4834		tests = append(tests, testCase{
4835			name: "Basic-Client-NoTicket",
4836			config: Config{
4837				MaxVersion:             VersionTLS12,
4838				SessionTicketsDisabled: true,
4839			},
4840			resumeSession: true,
4841		})
4842		tests = append(tests, testCase{
4843			testType: serverTest,
4844			name:     "Basic-Server",
4845			config: Config{
4846				MaxVersion: VersionTLS12,
4847				Bugs: ProtocolBugs{
4848					RequireSessionTickets: true,
4849				},
4850			},
4851			resumeSession: true,
4852			flags: []string{
4853				"-expect-no-session-id",
4854				"-expect-no-hrr",
4855			},
4856		})
4857		tests = append(tests, testCase{
4858			testType: serverTest,
4859			name:     "Basic-Server-NoTickets",
4860			config: Config{
4861				MaxVersion:             VersionTLS12,
4862				SessionTicketsDisabled: true,
4863			},
4864			resumeSession: true,
4865			flags:         []string{"-expect-session-id"},
4866		})
4867		tests = append(tests, testCase{
4868			testType: serverTest,
4869			name:     "Basic-Server-EarlyCallback",
4870			config: Config{
4871				MaxVersion: VersionTLS12,
4872			},
4873			flags:         []string{"-use-early-callback"},
4874			resumeSession: true,
4875		})
4876	}
4877
4878	// TLS 1.3 basic handshake shapes. DTLS 1.3 isn't supported yet.
4879	if config.protocol != dtls {
4880		tests = append(tests, testCase{
4881			name: "TLS13-1RTT-Client",
4882			config: Config{
4883				MaxVersion: VersionTLS13,
4884				MinVersion: VersionTLS13,
4885			},
4886			resumeSession:        true,
4887			resumeRenewedSession: true,
4888			// 0-RTT being disabled overrides all other 0-RTT reasons.
4889			flags: []string{"-expect-early-data-reason", "disabled"},
4890		})
4891
4892		tests = append(tests, testCase{
4893			testType: serverTest,
4894			name:     "TLS13-1RTT-Server",
4895			config: Config{
4896				MaxVersion: VersionTLS13,
4897				MinVersion: VersionTLS13,
4898			},
4899			resumeSession:        true,
4900			resumeRenewedSession: true,
4901			flags: []string{
4902				// TLS 1.3 uses tickets, so the session should not be
4903				// cached statefully.
4904				"-expect-no-session-id",
4905				// 0-RTT being disabled overrides all other 0-RTT reasons.
4906				"-expect-early-data-reason", "disabled",
4907			},
4908		})
4909
4910		tests = append(tests, testCase{
4911			name: "TLS13-HelloRetryRequest-Client",
4912			config: Config{
4913				MaxVersion: VersionTLS13,
4914				MinVersion: VersionTLS13,
4915				// P-384 requires a HelloRetryRequest against BoringSSL's default
4916				// configuration. Assert this with ExpectMissingKeyShare.
4917				CurvePreferences: []CurveID{CurveP384},
4918				Bugs: ProtocolBugs{
4919					ExpectMissingKeyShare: true,
4920				},
4921			},
4922			// Cover HelloRetryRequest during an ECDHE-PSK resumption.
4923			resumeSession: true,
4924			flags:         []string{"-expect-hrr"},
4925		})
4926
4927		tests = append(tests, testCase{
4928			testType: serverTest,
4929			name:     "TLS13-HelloRetryRequest-Server",
4930			config: Config{
4931				MaxVersion: VersionTLS13,
4932				MinVersion: VersionTLS13,
4933				// Require a HelloRetryRequest for every curve.
4934				DefaultCurves: []CurveID{},
4935			},
4936			// Cover HelloRetryRequest during an ECDHE-PSK resumption.
4937			resumeSession: true,
4938			flags:         []string{"-expect-hrr"},
4939		})
4940
4941		// Tests that specify a MaxEarlyDataSize don't work with QUIC.
4942		if config.protocol != quic {
4943			tests = append(tests, testCase{
4944				testType: clientTest,
4945				name:     "TLS13-EarlyData-TooMuchData-Client",
4946				config: Config{
4947					MaxVersion:       VersionTLS13,
4948					MinVersion:       VersionTLS13,
4949					MaxEarlyDataSize: 2,
4950				},
4951				resumeConfig: &Config{
4952					MaxVersion:       VersionTLS13,
4953					MinVersion:       VersionTLS13,
4954					MaxEarlyDataSize: 2,
4955					Bugs: ProtocolBugs{
4956						ExpectEarlyData: [][]byte{[]byte(shimInitialWrite[:2])},
4957					},
4958				},
4959				resumeShimPrefix: shimInitialWrite[2:],
4960				resumeSession:    true,
4961				earlyData:        true,
4962			})
4963		}
4964
4965		// Unfinished writes can only be tested when operations are async. EarlyData
4966		// can't be tested as part of an ImplicitHandshake in this case since
4967		// otherwise the early data will be sent as normal data.
4968		//
4969		// Note application data is external in QUIC, so unfinished writes do not
4970		// apply.
4971		if config.async && !config.implicitHandshake && config.protocol != quic {
4972			tests = append(tests, testCase{
4973				testType: clientTest,
4974				name:     "TLS13-EarlyData-UnfinishedWrite-Client",
4975				config: Config{
4976					MaxVersion: VersionTLS13,
4977					MinVersion: VersionTLS13,
4978					Bugs: ProtocolBugs{
4979						// Write the server response before expecting early data.
4980						ExpectEarlyData:     [][]byte{},
4981						ExpectLateEarlyData: [][]byte{[]byte(shimInitialWrite)},
4982					},
4983				},
4984				resumeSession: true,
4985				earlyData:     true,
4986				flags:         []string{"-on-resume-read-with-unfinished-write"},
4987			})
4988
4989			// Rejected unfinished writes are discarded (from the
4990			// perspective of the calling application) on 0-RTT
4991			// reject.
4992			tests = append(tests, testCase{
4993				testType: clientTest,
4994				name:     "TLS13-EarlyData-RejectUnfinishedWrite-Client",
4995				config: Config{
4996					MaxVersion: VersionTLS13,
4997					MinVersion: VersionTLS13,
4998					Bugs: ProtocolBugs{
4999						AlwaysRejectEarlyData: true,
5000					},
5001				},
5002				resumeSession:           true,
5003				earlyData:               true,
5004				expectEarlyDataRejected: true,
5005				flags:                   []string{"-on-resume-read-with-unfinished-write"},
5006			})
5007		}
5008
5009		// Early data has no size limit in QUIC.
5010		if config.protocol != quic {
5011			tests = append(tests, testCase{
5012				testType: serverTest,
5013				name:     "TLS13-MaxEarlyData-Server",
5014				config: Config{
5015					MaxVersion: VersionTLS13,
5016					MinVersion: VersionTLS13,
5017					Bugs: ProtocolBugs{
5018						SendEarlyData:           [][]byte{bytes.Repeat([]byte{1}, 14336+1)},
5019						ExpectEarlyDataAccepted: true,
5020					},
5021				},
5022				messageCount:  2,
5023				resumeSession: true,
5024				earlyData:     true,
5025				shouldFail:    true,
5026				expectedError: ":TOO_MUCH_READ_EARLY_DATA:",
5027			})
5028		}
5029	}
5030
5031	// TLS client auth.
5032	// The following tests have a max version of 1.2, so they are not suitable
5033	// for use with QUIC.
5034	if config.protocol != quic {
5035		tests = append(tests, testCase{
5036			testType: clientTest,
5037			name:     "ClientAuth-NoCertificate-Client",
5038			config: Config{
5039				MaxVersion: VersionTLS12,
5040				ClientAuth: RequestClientCert,
5041			},
5042		})
5043		tests = append(tests, testCase{
5044			testType: serverTest,
5045			name:     "ClientAuth-NoCertificate-Server",
5046			config: Config{
5047				MaxVersion: VersionTLS12,
5048			},
5049			// Setting SSL_VERIFY_PEER allows anonymous clients.
5050			flags: []string{"-verify-peer"},
5051		})
5052	}
5053	if config.protocol != dtls {
5054		tests = append(tests, testCase{
5055			testType: clientTest,
5056			name:     "ClientAuth-NoCertificate-Client-TLS13",
5057			config: Config{
5058				MaxVersion: VersionTLS13,
5059				ClientAuth: RequestClientCert,
5060			},
5061		})
5062		tests = append(tests, testCase{
5063			testType: serverTest,
5064			name:     "ClientAuth-NoCertificate-Server-TLS13",
5065			config: Config{
5066				MaxVersion: VersionTLS13,
5067			},
5068			// Setting SSL_VERIFY_PEER allows anonymous clients.
5069			flags: []string{"-verify-peer"},
5070		})
5071	}
5072	if config.protocol != quic {
5073		tests = append(tests, testCase{
5074			testType: clientTest,
5075			name:     "ClientAuth-RSA-Client",
5076			config: Config{
5077				MaxVersion: VersionTLS12,
5078				ClientAuth: RequireAnyClientCert,
5079			},
5080			shimCertificate: &rsaCertificate,
5081		})
5082	}
5083	tests = append(tests, testCase{
5084		testType: clientTest,
5085		name:     "ClientAuth-RSA-Client-TLS13",
5086		config: Config{
5087			MaxVersion: VersionTLS13,
5088			ClientAuth: RequireAnyClientCert,
5089		},
5090		shimCertificate: &rsaCertificate,
5091	})
5092	if config.protocol != quic {
5093		tests = append(tests, testCase{
5094			testType: clientTest,
5095			name:     "ClientAuth-ECDSA-Client",
5096			config: Config{
5097				MaxVersion: VersionTLS12,
5098				ClientAuth: RequireAnyClientCert,
5099			},
5100			shimCertificate: &ecdsaP256Certificate,
5101		})
5102	}
5103	tests = append(tests, testCase{
5104		testType: clientTest,
5105		name:     "ClientAuth-ECDSA-Client-TLS13",
5106		config: Config{
5107			MaxVersion: VersionTLS13,
5108			ClientAuth: RequireAnyClientCert,
5109		},
5110		shimCertificate: &ecdsaP256Certificate,
5111	})
5112	if config.protocol != quic {
5113		tests = append(tests, testCase{
5114			testType: clientTest,
5115			name:     "ClientAuth-NoCertificate-OldCallback",
5116			config: Config{
5117				MaxVersion: VersionTLS12,
5118				ClientAuth: RequestClientCert,
5119			},
5120			flags: []string{"-use-old-client-cert-callback"},
5121		})
5122	}
5123	tests = append(tests, testCase{
5124		testType: clientTest,
5125		name:     "ClientAuth-NoCertificate-OldCallback-TLS13",
5126		config: Config{
5127			MaxVersion: VersionTLS13,
5128			ClientAuth: RequestClientCert,
5129		},
5130		flags: []string{"-use-old-client-cert-callback"},
5131	})
5132	if config.protocol != quic {
5133		tests = append(tests, testCase{
5134			testType: clientTest,
5135			name:     "ClientAuth-OldCallback",
5136			config: Config{
5137				MaxVersion: VersionTLS12,
5138				ClientAuth: RequireAnyClientCert,
5139			},
5140			shimCertificate: &rsaCertificate,
5141			flags: []string{
5142				"-use-old-client-cert-callback",
5143			},
5144		})
5145	}
5146	tests = append(tests, testCase{
5147		testType: clientTest,
5148		name:     "ClientAuth-OldCallback-TLS13",
5149		config: Config{
5150			MaxVersion: VersionTLS13,
5151			ClientAuth: RequireAnyClientCert,
5152		},
5153		shimCertificate: &rsaCertificate,
5154		flags: []string{
5155			"-use-old-client-cert-callback",
5156		},
5157	})
5158	if config.protocol != quic {
5159		tests = append(tests, testCase{
5160			testType: serverTest,
5161			name:     "ClientAuth-Server",
5162			config: Config{
5163				MaxVersion: VersionTLS12,
5164				Credential: &rsaCertificate,
5165			},
5166			flags: []string{"-require-any-client-certificate"},
5167		})
5168	}
5169	tests = append(tests, testCase{
5170		testType: serverTest,
5171		name:     "ClientAuth-Server-TLS13",
5172		config: Config{
5173			MaxVersion: VersionTLS13,
5174			Credential: &rsaCertificate,
5175		},
5176		flags: []string{"-require-any-client-certificate"},
5177	})
5178
5179	// Test each key exchange on the server side for async keys.
5180	if config.protocol != quic {
5181		tests = append(tests, testCase{
5182			testType: serverTest,
5183			name:     "Basic-Server-RSA",
5184			config: Config{
5185				MaxVersion:   VersionTLS12,
5186				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
5187			},
5188			shimCertificate: &rsaCertificate,
5189		})
5190		tests = append(tests, testCase{
5191			testType: serverTest,
5192			name:     "Basic-Server-ECDHE-RSA",
5193			config: Config{
5194				MaxVersion:   VersionTLS12,
5195				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5196			},
5197			shimCertificate: &rsaCertificate,
5198		})
5199		tests = append(tests, testCase{
5200			testType: serverTest,
5201			name:     "Basic-Server-ECDHE-ECDSA",
5202			config: Config{
5203				MaxVersion:   VersionTLS12,
5204				CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
5205			},
5206			shimCertificate: &ecdsaP256Certificate,
5207		})
5208		tests = append(tests, testCase{
5209			testType: serverTest,
5210			name:     "Basic-Server-Ed25519",
5211			config: Config{
5212				MaxVersion:   VersionTLS12,
5213				CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
5214			},
5215			shimCertificate: &ed25519Certificate,
5216			flags: []string{
5217				"-verify-prefs", strconv.Itoa(int(signatureEd25519)),
5218			},
5219		})
5220
5221		// No session ticket support; server doesn't send NewSessionTicket.
5222		tests = append(tests, testCase{
5223			name: "SessionTicketsDisabled-Client",
5224			config: Config{
5225				MaxVersion:             VersionTLS12,
5226				SessionTicketsDisabled: true,
5227			},
5228		})
5229		tests = append(tests, testCase{
5230			testType: serverTest,
5231			name:     "SessionTicketsDisabled-Server",
5232			config: Config{
5233				MaxVersion:             VersionTLS12,
5234				SessionTicketsDisabled: true,
5235			},
5236		})
5237
5238		// Skip ServerKeyExchange in PSK key exchange if there's no
5239		// identity hint.
5240		tests = append(tests, testCase{
5241			name: "EmptyPSKHint-Client",
5242			config: Config{
5243				MaxVersion:   VersionTLS12,
5244				CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
5245				PreSharedKey: []byte("secret"),
5246			},
5247			flags: []string{"-psk", "secret"},
5248		})
5249		tests = append(tests, testCase{
5250			testType: serverTest,
5251			name:     "EmptyPSKHint-Server",
5252			config: Config{
5253				MaxVersion:   VersionTLS12,
5254				CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
5255				PreSharedKey: []byte("secret"),
5256			},
5257			flags: []string{"-psk", "secret"},
5258		})
5259	}
5260
5261	// OCSP stapling tests.
5262	for _, vers := range allVersions(config.protocol) {
5263		tests = append(tests, testCase{
5264			testType: clientTest,
5265			name:     "OCSPStapling-Client-" + vers.name,
5266			config: Config{
5267				MaxVersion: vers.version,
5268				Credential: rsaCertificate.WithOCSP(testOCSPResponse),
5269			},
5270			flags: []string{
5271				"-enable-ocsp-stapling",
5272				"-expect-ocsp-response",
5273				base64FlagValue(testOCSPResponse),
5274				"-verify-peer",
5275			},
5276			resumeSession: true,
5277		})
5278		tests = append(tests, testCase{
5279			testType: serverTest,
5280			name:     "OCSPStapling-Server-" + vers.name,
5281			config: Config{
5282				MaxVersion: vers.version,
5283			},
5284			expectations: connectionExpectations{
5285				peerCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
5286			},
5287			shimCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
5288			resumeSession:   true,
5289		})
5290
5291		// The client OCSP callback is an alternate certificate
5292		// verification callback.
5293		tests = append(tests, testCase{
5294			testType: clientTest,
5295			name:     "ClientOCSPCallback-Pass-" + vers.name,
5296			config: Config{
5297				MaxVersion: vers.version,
5298				Credential: rsaCertificate.WithOCSP(testOCSPResponse),
5299			},
5300			flags: []string{
5301				"-enable-ocsp-stapling",
5302				"-use-ocsp-callback",
5303			},
5304		})
5305		var expectedLocalError string
5306		if !config.async {
5307			// TODO(davidben): Asynchronous fatal alerts are never
5308			// sent. https://crbug.com/boringssl/130.
5309			expectedLocalError = "remote error: bad certificate status response"
5310		}
5311		tests = append(tests, testCase{
5312			testType: clientTest,
5313			name:     "ClientOCSPCallback-Fail-" + vers.name,
5314			config: Config{
5315				MaxVersion: vers.version,
5316				Credential: rsaCertificate.WithOCSP(testOCSPResponse),
5317			},
5318			flags: []string{
5319				"-enable-ocsp-stapling",
5320				"-use-ocsp-callback",
5321				"-fail-ocsp-callback",
5322			},
5323			shouldFail:         true,
5324			expectedLocalError: expectedLocalError,
5325			expectedError:      ":OCSP_CB_ERROR:",
5326		})
5327		// The callback still runs if the server does not send an OCSP
5328		// response.
5329		tests = append(tests, testCase{
5330			testType: clientTest,
5331			name:     "ClientOCSPCallback-FailNoStaple-" + vers.name,
5332			config: Config{
5333				MaxVersion: vers.version,
5334				Credential: &rsaCertificate,
5335			},
5336			flags: []string{
5337				"-enable-ocsp-stapling",
5338				"-use-ocsp-callback",
5339				"-fail-ocsp-callback",
5340			},
5341			shouldFail:         true,
5342			expectedLocalError: expectedLocalError,
5343			expectedError:      ":OCSP_CB_ERROR:",
5344		})
5345
5346		// The server OCSP callback is a legacy mechanism for
5347		// configuring OCSP, used by unreliable server software.
5348		tests = append(tests, testCase{
5349			testType: serverTest,
5350			name:     "ServerOCSPCallback-SetInCallback-" + vers.name,
5351			config: Config{
5352				MaxVersion: vers.version,
5353			},
5354			shimCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
5355			expectations: connectionExpectations{
5356				peerCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
5357			},
5358			flags: []string{
5359				"-use-ocsp-callback",
5360				"-set-ocsp-in-callback",
5361			},
5362			resumeSession: true,
5363		})
5364
5365		// The callback may decline OCSP, in which case  we act as if
5366		// the client did not support it, even if a response was
5367		// configured.
5368		tests = append(tests, testCase{
5369			testType: serverTest,
5370			name:     "ServerOCSPCallback-Decline-" + vers.name,
5371			config: Config{
5372				MaxVersion: vers.version,
5373			},
5374			shimCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
5375			expectations: connectionExpectations{
5376				// There should be no OCSP response from the peer.
5377				peerCertificate: &rsaCertificate,
5378			},
5379			flags: []string{
5380				"-use-ocsp-callback",
5381				"-decline-ocsp-callback",
5382			},
5383			resumeSession: true,
5384		})
5385
5386		// The callback may also signal an internal error.
5387		tests = append(tests, testCase{
5388			testType: serverTest,
5389			name:     "ServerOCSPCallback-Fail-" + vers.name,
5390			config: Config{
5391				MaxVersion: vers.version,
5392			},
5393			shimCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
5394			flags: []string{
5395				"-use-ocsp-callback",
5396				"-fail-ocsp-callback",
5397			},
5398			shouldFail:    true,
5399			expectedError: ":OCSP_CB_ERROR:",
5400		})
5401	}
5402
5403	// Certificate verification tests.
5404	for _, vers := range allVersions(config.protocol) {
5405		for _, useCustomCallback := range []bool{false, true} {
5406			for _, testType := range []testType{clientTest, serverTest} {
5407				suffix := "-Client"
5408				if testType == serverTest {
5409					suffix = "-Server"
5410				}
5411				suffix += "-" + vers.name
5412				if useCustomCallback {
5413					suffix += "-CustomCallback"
5414				}
5415
5416				// The custom callback and legacy callback have different default
5417				// alerts.
5418				verifyFailLocalError := "remote error: handshake failure"
5419				if useCustomCallback {
5420					verifyFailLocalError = "remote error: unknown certificate"
5421				}
5422
5423				// We do not reliably send asynchronous fatal alerts. See
5424				// https://crbug.com/boringssl/130.
5425				if config.async {
5426					verifyFailLocalError = ""
5427				}
5428
5429				flags := []string{"-verify-peer"}
5430				if testType == serverTest {
5431					flags = append(flags, "-require-any-client-certificate")
5432				}
5433				if useCustomCallback {
5434					flags = append(flags, "-use-custom-verify-callback")
5435				}
5436
5437				tests = append(tests, testCase{
5438					testType: testType,
5439					name:     "CertificateVerificationSucceed" + suffix,
5440					config: Config{
5441						MaxVersion: vers.version,
5442						Credential: &rsaCertificate,
5443					},
5444					flags:         append([]string{"-expect-verify-result"}, flags...),
5445					resumeSession: true,
5446				})
5447				tests = append(tests, testCase{
5448					testType: testType,
5449					name:     "CertificateVerificationFail" + suffix,
5450					config: Config{
5451						MaxVersion: vers.version,
5452						Credential: &rsaCertificate,
5453					},
5454					flags:              append([]string{"-verify-fail"}, flags...),
5455					shouldFail:         true,
5456					expectedError:      ":CERTIFICATE_VERIFY_FAILED:",
5457					expectedLocalError: verifyFailLocalError,
5458				})
5459				// Tests that although the verify callback fails on resumption, by default we don't call it.
5460				tests = append(tests, testCase{
5461					testType: testType,
5462					name:     "CertificateVerificationDoesNotFailOnResume" + suffix,
5463					config: Config{
5464						MaxVersion: vers.version,
5465						Credential: &rsaCertificate,
5466					},
5467					flags:         append([]string{"-on-resume-verify-fail"}, flags...),
5468					resumeSession: true,
5469				})
5470				if testType == clientTest && useCustomCallback {
5471					tests = append(tests, testCase{
5472						testType: testType,
5473						name:     "CertificateVerificationFailsOnResume" + suffix,
5474						config: Config{
5475							MaxVersion: vers.version,
5476							Credential: &rsaCertificate,
5477						},
5478						flags: append([]string{
5479							"-on-resume-verify-fail",
5480							"-reverify-on-resume",
5481						}, flags...),
5482						resumeSession:      true,
5483						shouldFail:         true,
5484						expectedError:      ":CERTIFICATE_VERIFY_FAILED:",
5485						expectedLocalError: verifyFailLocalError,
5486					})
5487					tests = append(tests, testCase{
5488						testType: testType,
5489						name:     "CertificateVerificationPassesOnResume" + suffix,
5490						config: Config{
5491							MaxVersion: vers.version,
5492							Credential: &rsaCertificate,
5493						},
5494						flags: append([]string{
5495							"-reverify-on-resume",
5496						}, flags...),
5497						resumeSession: true,
5498					})
5499					if vers.version >= VersionTLS13 {
5500						tests = append(tests, testCase{
5501							testType: testType,
5502							name:     "EarlyData-RejectTicket-Client-Reverify" + suffix,
5503							config: Config{
5504								MaxVersion: vers.version,
5505							},
5506							resumeConfig: &Config{
5507								MaxVersion:             vers.version,
5508								SessionTicketsDisabled: true,
5509							},
5510							resumeSession:           true,
5511							expectResumeRejected:    true,
5512							earlyData:               true,
5513							expectEarlyDataRejected: true,
5514							flags: append([]string{
5515								"-reverify-on-resume",
5516								// Session tickets are disabled, so the runner will not send a ticket.
5517								"-on-retry-expect-no-session",
5518							}, flags...),
5519						})
5520						tests = append(tests, testCase{
5521							testType: testType,
5522							name:     "EarlyData-Reject0RTT-Client-Reverify" + suffix,
5523							config: Config{
5524								MaxVersion: vers.version,
5525								Bugs: ProtocolBugs{
5526									AlwaysRejectEarlyData: true,
5527								},
5528							},
5529							resumeSession:           true,
5530							expectResumeRejected:    false,
5531							earlyData:               true,
5532							expectEarlyDataRejected: true,
5533							flags: append([]string{
5534								"-reverify-on-resume",
5535							}, flags...),
5536						})
5537						tests = append(tests, testCase{
5538							testType: testType,
5539							name:     "EarlyData-RejectTicket-Client-ReverifyFails" + suffix,
5540							config: Config{
5541								MaxVersion: vers.version,
5542							},
5543							resumeConfig: &Config{
5544								MaxVersion:             vers.version,
5545								SessionTicketsDisabled: true,
5546							},
5547							resumeSession:           true,
5548							expectResumeRejected:    true,
5549							earlyData:               true,
5550							expectEarlyDataRejected: true,
5551							shouldFail:              true,
5552							expectedError:           ":CERTIFICATE_VERIFY_FAILED:",
5553							flags: append([]string{
5554								"-reverify-on-resume",
5555								// Session tickets are disabled, so the runner will not send a ticket.
5556								"-on-retry-expect-no-session",
5557								"-on-retry-verify-fail",
5558							}, flags...),
5559						})
5560						tests = append(tests, testCase{
5561							testType: testType,
5562							name:     "EarlyData-Reject0RTT-Client-ReverifyFails" + suffix,
5563							config: Config{
5564								MaxVersion: vers.version,
5565								Bugs: ProtocolBugs{
5566									AlwaysRejectEarlyData: true,
5567								},
5568							},
5569							resumeSession:           true,
5570							expectResumeRejected:    false,
5571							earlyData:               true,
5572							expectEarlyDataRejected: true,
5573							shouldFail:              true,
5574							expectedError:           ":CERTIFICATE_VERIFY_FAILED:",
5575							expectedLocalError:      verifyFailLocalError,
5576							flags: append([]string{
5577								"-reverify-on-resume",
5578								"-on-retry-verify-fail",
5579							}, flags...),
5580						})
5581						// This tests that we only call the verify callback once.
5582						tests = append(tests, testCase{
5583							testType: testType,
5584							name:     "EarlyData-Accept0RTT-Client-Reverify" + suffix,
5585							config: Config{
5586								MaxVersion: vers.version,
5587							},
5588							resumeSession: true,
5589							earlyData:     true,
5590							flags: append([]string{
5591								"-reverify-on-resume",
5592							}, flags...),
5593						})
5594						tests = append(tests, testCase{
5595							testType: testType,
5596							name:     "EarlyData-Accept0RTT-Client-ReverifyFails" + suffix,
5597							config: Config{
5598								MaxVersion: vers.version,
5599							},
5600							resumeSession: true,
5601							earlyData:     true,
5602							shouldFail:    true,
5603							expectedError: ":CERTIFICATE_VERIFY_FAILED:",
5604							// We do not set expectedLocalError here because the shim rejects
5605							// the connection without an alert.
5606							flags: append([]string{
5607								"-reverify-on-resume",
5608								"-on-resume-verify-fail",
5609							}, flags...),
5610						})
5611					}
5612				}
5613			}
5614		}
5615
5616		// By default, the client is in a soft fail mode where the peer
5617		// certificate is verified but failures are non-fatal.
5618		tests = append(tests, testCase{
5619			testType: clientTest,
5620			name:     "CertificateVerificationSoftFail-" + vers.name,
5621			config: Config{
5622				MaxVersion: vers.version,
5623				Credential: &rsaCertificate,
5624			},
5625			flags: []string{
5626				"-verify-fail",
5627				"-expect-verify-result",
5628			},
5629			resumeSession: true,
5630		})
5631	}
5632
5633	tests = append(tests, testCase{
5634		name:               "ShimSendAlert",
5635		flags:              []string{"-send-alert"},
5636		shimWritesFirst:    true,
5637		shouldFail:         true,
5638		expectedLocalError: "remote error: decompression failure",
5639	})
5640
5641	if config.protocol == tls {
5642		tests = append(tests, testCase{
5643			name: "Renegotiate-Client",
5644			config: Config{
5645				MaxVersion: VersionTLS12,
5646			},
5647			renegotiate: 1,
5648			flags: []string{
5649				"-renegotiate-freely",
5650				"-expect-total-renegotiations", "1",
5651			},
5652		})
5653
5654		tests = append(tests, testCase{
5655			name: "Renegotiate-Client-Explicit",
5656			config: Config{
5657				MaxVersion: VersionTLS12,
5658			},
5659			renegotiate: 1,
5660			flags: []string{
5661				"-renegotiate-explicit",
5662				"-expect-total-renegotiations", "1",
5663			},
5664		})
5665
5666		halfHelloRequestError := ":UNEXPECTED_RECORD:"
5667		if config.packHandshake {
5668			// If the HelloRequest is sent in the same record as the server Finished,
5669			// BoringSSL rejects it before the handshake completes.
5670			halfHelloRequestError = ":EXCESS_HANDSHAKE_DATA:"
5671		}
5672		tests = append(tests, testCase{
5673			name: "SendHalfHelloRequest",
5674			config: Config{
5675				MaxVersion: VersionTLS12,
5676				Bugs: ProtocolBugs{
5677					PackHelloRequestWithFinished: config.packHandshake,
5678				},
5679			},
5680			sendHalfHelloRequest: true,
5681			flags:                []string{"-renegotiate-ignore"},
5682			shouldFail:           true,
5683			expectedError:        halfHelloRequestError,
5684		})
5685
5686		// NPN on client and server; results in post-handshake message.
5687		tests = append(tests, testCase{
5688			name: "NPN-Client",
5689			config: Config{
5690				MaxVersion: VersionTLS12,
5691				NextProtos: []string{"foo"},
5692			},
5693			flags:         []string{"-select-next-proto", "foo"},
5694			resumeSession: true,
5695			expectations: connectionExpectations{
5696				nextProto:     "foo",
5697				nextProtoType: npn,
5698			},
5699		})
5700		tests = append(tests, testCase{
5701			testType: serverTest,
5702			name:     "NPN-Server",
5703			config: Config{
5704				MaxVersion: VersionTLS12,
5705				NextProtos: []string{"bar"},
5706			},
5707			flags: []string{
5708				"-advertise-npn", "\x03foo\x03bar\x03baz",
5709				"-expect-next-proto", "bar",
5710			},
5711			resumeSession: true,
5712			expectations: connectionExpectations{
5713				nextProto:     "bar",
5714				nextProtoType: npn,
5715			},
5716		})
5717
5718		// Client does False Start and negotiates NPN.
5719		tests = append(tests, testCase{
5720			name: "FalseStart",
5721			config: Config{
5722				MaxVersion:   VersionTLS12,
5723				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5724				NextProtos:   []string{"foo"},
5725				Bugs: ProtocolBugs{
5726					ExpectFalseStart: true,
5727				},
5728			},
5729			flags: []string{
5730				"-false-start",
5731				"-select-next-proto", "foo",
5732			},
5733			shimWritesFirst: true,
5734			resumeSession:   true,
5735		})
5736
5737		// Client does False Start and negotiates ALPN.
5738		tests = append(tests, testCase{
5739			name: "FalseStart-ALPN",
5740			config: Config{
5741				MaxVersion:   VersionTLS12,
5742				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5743				NextProtos:   []string{"foo"},
5744				Bugs: ProtocolBugs{
5745					ExpectFalseStart: true,
5746				},
5747			},
5748			flags: []string{
5749				"-false-start",
5750				"-advertise-alpn", "\x03foo",
5751				"-expect-alpn", "foo",
5752			},
5753			shimWritesFirst: true,
5754			resumeSession:   true,
5755		})
5756
5757		// False Start without session tickets.
5758		tests = append(tests, testCase{
5759			name: "FalseStart-SessionTicketsDisabled",
5760			config: Config{
5761				MaxVersion:             VersionTLS12,
5762				CipherSuites:           []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
5763				NextProtos:             []string{"foo"},
5764				SessionTicketsDisabled: true,
5765				Bugs: ProtocolBugs{
5766					ExpectFalseStart: true,
5767				},
5768			},
5769			flags: []string{
5770				"-false-start",
5771				"-select-next-proto", "foo",
5772			},
5773			shimWritesFirst: true,
5774		})
5775
5776		// Server parses a V2ClientHello. Test different lengths for the
5777		// challenge field.
5778		for _, challengeLength := range []int{16, 31, 32, 33, 48} {
5779			tests = append(tests, testCase{
5780				testType: serverTest,
5781				name:     fmt.Sprintf("SendV2ClientHello-%d", challengeLength),
5782				config: Config{
5783					// Choose a cipher suite that does not involve
5784					// elliptic curves, so no extensions are
5785					// involved.
5786					MaxVersion:   VersionTLS12,
5787					CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
5788					Bugs: ProtocolBugs{
5789						SendV2ClientHello:            true,
5790						V2ClientHelloChallengeLength: challengeLength,
5791					},
5792				},
5793				flags: []string{
5794					"-expect-msg-callback",
5795					`read v2clienthello
5796write hs 2
5797write hs 11
5798write hs 14
5799read hs 16
5800read ccs
5801read hs 20
5802write ccs
5803write hs 20
5804read alert 1 0
5805`,
5806				},
5807			})
5808		}
5809
5810		// Channel ID and NPN at the same time, to ensure their relative
5811		// ordering is correct.
5812		tests = append(tests, testCase{
5813			name: "ChannelID-NPN-Client",
5814			config: Config{
5815				MaxVersion:       VersionTLS12,
5816				RequestChannelID: true,
5817				NextProtos:       []string{"foo"},
5818			},
5819			flags: []string{
5820				"-send-channel-id", channelIDKeyPath,
5821				"-select-next-proto", "foo",
5822			},
5823			resumeSession: true,
5824			expectations: connectionExpectations{
5825				channelID:     true,
5826				nextProto:     "foo",
5827				nextProtoType: npn,
5828			},
5829		})
5830		tests = append(tests, testCase{
5831			testType: serverTest,
5832			name:     "ChannelID-NPN-Server",
5833			config: Config{
5834				MaxVersion: VersionTLS12,
5835				ChannelID:  &channelIDKey,
5836				NextProtos: []string{"bar"},
5837			},
5838			flags: []string{
5839				"-expect-channel-id",
5840				base64FlagValue(channelIDBytes),
5841				"-advertise-npn", "\x03foo\x03bar\x03baz",
5842				"-expect-next-proto", "bar",
5843			},
5844			resumeSession: true,
5845			expectations: connectionExpectations{
5846				channelID:     true,
5847				nextProto:     "bar",
5848				nextProtoType: npn,
5849			},
5850		})
5851
5852		// Bidirectional shutdown with the runner initiating.
5853		tests = append(tests, testCase{
5854			name: "Shutdown-Runner",
5855			config: Config{
5856				Bugs: ProtocolBugs{
5857					ExpectCloseNotify: true,
5858				},
5859			},
5860			flags: []string{"-check-close-notify"},
5861		})
5862	}
5863	if config.protocol != dtls {
5864		// Test Channel ID
5865		for _, ver := range allVersions(config.protocol) {
5866			if ver.version < VersionTLS10 {
5867				continue
5868			}
5869			// Client sends a Channel ID.
5870			tests = append(tests, testCase{
5871				name: "ChannelID-Client-" + ver.name,
5872				config: Config{
5873					MaxVersion:       ver.version,
5874					RequestChannelID: true,
5875				},
5876				flags:         []string{"-send-channel-id", channelIDKeyPath},
5877				resumeSession: true,
5878				expectations: connectionExpectations{
5879					channelID: true,
5880				},
5881			})
5882
5883			// Server accepts a Channel ID.
5884			tests = append(tests, testCase{
5885				testType: serverTest,
5886				name:     "ChannelID-Server-" + ver.name,
5887				config: Config{
5888					MaxVersion: ver.version,
5889					ChannelID:  &channelIDKey,
5890				},
5891				flags: []string{
5892					"-expect-channel-id",
5893					base64FlagValue(channelIDBytes),
5894				},
5895				resumeSession: true,
5896				expectations: connectionExpectations{
5897					channelID: true,
5898				},
5899			})
5900
5901			tests = append(tests, testCase{
5902				testType: serverTest,
5903				name:     "InvalidChannelIDSignature-" + ver.name,
5904				config: Config{
5905					MaxVersion: ver.version,
5906					ChannelID:  &channelIDKey,
5907					Bugs: ProtocolBugs{
5908						InvalidChannelIDSignature: true,
5909					},
5910				},
5911				flags:         []string{"-enable-channel-id"},
5912				shouldFail:    true,
5913				expectedError: ":CHANNEL_ID_SIGNATURE_INVALID:",
5914			})
5915
5916			if ver.version < VersionTLS13 {
5917				// Channel ID requires ECDHE ciphers.
5918				tests = append(tests, testCase{
5919					testType: serverTest,
5920					name:     "ChannelID-NoECDHE-" + ver.name,
5921					config: Config{
5922						MaxVersion:   ver.version,
5923						CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
5924						ChannelID:    &channelIDKey,
5925					},
5926					expectations: connectionExpectations{
5927						channelID: false,
5928					},
5929					flags: []string{"-enable-channel-id"},
5930				})
5931
5932				// Sanity-check setting expectations.channelID false works.
5933				tests = append(tests, testCase{
5934					testType: serverTest,
5935					name:     "ChannelID-ECDHE-" + ver.name,
5936					config: Config{
5937						MaxVersion:   ver.version,
5938						CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
5939						ChannelID:    &channelIDKey,
5940					},
5941					expectations: connectionExpectations{
5942						channelID: false,
5943					},
5944					flags:              []string{"-enable-channel-id"},
5945					shouldFail:         true,
5946					expectedLocalError: "channel ID unexpectedly negotiated",
5947				})
5948			}
5949		}
5950
5951		if !config.implicitHandshake {
5952			// Bidirectional shutdown with the shim initiating. The runner,
5953			// in the meantime, sends garbage before the close_notify which
5954			// the shim must ignore. This test is disabled under implicit
5955			// handshake tests because the shim never reads or writes.
5956
5957			// Tests that require checking for a close notify alert don't work with
5958			// QUIC because alerts are handled outside of the TLS stack in QUIC.
5959			if config.protocol != quic {
5960				tests = append(tests, testCase{
5961					name: "Shutdown-Shim",
5962					config: Config{
5963						MaxVersion: VersionTLS12,
5964						Bugs: ProtocolBugs{
5965							ExpectCloseNotify: true,
5966						},
5967					},
5968					shimShutsDown:     true,
5969					sendEmptyRecords:  1,
5970					sendWarningAlerts: 1,
5971					flags:             []string{"-check-close-notify"},
5972				})
5973
5974				// The shim should reject unexpected application data
5975				// when shutting down.
5976				tests = append(tests, testCase{
5977					name: "Shutdown-Shim-ApplicationData",
5978					config: Config{
5979						MaxVersion: VersionTLS12,
5980						Bugs: ProtocolBugs{
5981							ExpectCloseNotify: true,
5982						},
5983					},
5984					shimShutsDown:     true,
5985					messageCount:      1,
5986					sendEmptyRecords:  1,
5987					sendWarningAlerts: 1,
5988					flags:             []string{"-check-close-notify"},
5989					shouldFail:        true,
5990					expectedError:     ":APPLICATION_DATA_ON_SHUTDOWN:",
5991				})
5992
5993				// Test that SSL_shutdown still processes KeyUpdate.
5994				tests = append(tests, testCase{
5995					name: "Shutdown-Shim-KeyUpdate",
5996					config: Config{
5997						MinVersion: VersionTLS13,
5998						MaxVersion: VersionTLS13,
5999						Bugs: ProtocolBugs{
6000							ExpectCloseNotify: true,
6001						},
6002					},
6003					shimShutsDown:    true,
6004					sendKeyUpdates:   1,
6005					keyUpdateRequest: keyUpdateRequested,
6006					flags:            []string{"-check-close-notify"},
6007				})
6008
6009				// Test that SSL_shutdown processes HelloRequest
6010				// correctly.
6011				tests = append(tests, testCase{
6012					name: "Shutdown-Shim-HelloRequest-Ignore",
6013					config: Config{
6014						MinVersion: VersionTLS12,
6015						MaxVersion: VersionTLS12,
6016						Bugs: ProtocolBugs{
6017							SendHelloRequestBeforeEveryAppDataRecord: true,
6018							ExpectCloseNotify:                        true,
6019						},
6020					},
6021					shimShutsDown: true,
6022					flags: []string{
6023						"-renegotiate-ignore",
6024						"-check-close-notify",
6025					},
6026				})
6027				tests = append(tests, testCase{
6028					name: "Shutdown-Shim-HelloRequest-Reject",
6029					config: Config{
6030						MinVersion: VersionTLS12,
6031						MaxVersion: VersionTLS12,
6032						Bugs: ProtocolBugs{
6033							ExpectCloseNotify: true,
6034						},
6035					},
6036					shimShutsDown: true,
6037					renegotiate:   1,
6038					shouldFail:    true,
6039					expectedError: ":NO_RENEGOTIATION:",
6040					flags:         []string{"-check-close-notify"},
6041				})
6042				tests = append(tests, testCase{
6043					name: "Shutdown-Shim-HelloRequest-CannotHandshake",
6044					config: Config{
6045						MinVersion: VersionTLS12,
6046						MaxVersion: VersionTLS12,
6047						Bugs: ProtocolBugs{
6048							ExpectCloseNotify: true,
6049						},
6050					},
6051					shimShutsDown: true,
6052					renegotiate:   1,
6053					shouldFail:    true,
6054					expectedError: ":NO_RENEGOTIATION:",
6055					flags: []string{
6056						"-check-close-notify",
6057						"-renegotiate-freely",
6058					},
6059				})
6060
6061				tests = append(tests, testCase{
6062					testType: serverTest,
6063					name:     "Shutdown-Shim-Renegotiate-Server-Forbidden",
6064					config: Config{
6065						MaxVersion: VersionTLS12,
6066						Bugs: ProtocolBugs{
6067							ExpectCloseNotify: true,
6068						},
6069					},
6070					shimShutsDown: true,
6071					renegotiate:   1,
6072					shouldFail:    true,
6073					expectedError: ":NO_RENEGOTIATION:",
6074					flags: []string{
6075						"-check-close-notify",
6076					},
6077				})
6078			}
6079		}
6080	}
6081	if config.protocol == dtls {
6082		// TODO(davidben): DTLS 1.3 will want a similar thing for
6083		// HelloRetryRequest.
6084		tests = append(tests, testCase{
6085			name: "SkipHelloVerifyRequest",
6086			config: Config{
6087				MaxVersion: VersionTLS12,
6088				Bugs: ProtocolBugs{
6089					SkipHelloVerifyRequest: true,
6090				},
6091			},
6092		})
6093	}
6094
6095	for _, test := range tests {
6096		test.protocol = config.protocol
6097		test.name += "-" + config.protocol.String()
6098		if config.async {
6099			test.name += "-Async"
6100			test.flags = append(test.flags, "-async")
6101		} else {
6102			test.name += "-Sync"
6103		}
6104		if config.splitHandshake {
6105			test.name += "-SplitHandshakeRecords"
6106			test.config.Bugs.MaxHandshakeRecordLength = 1
6107			if config.protocol == dtls {
6108				test.config.Bugs.MaxPacketLength = 256
6109				test.flags = append(test.flags, "-mtu", "256")
6110			}
6111		}
6112		if config.packHandshake {
6113			test.name += "-PackHandshake"
6114			if config.protocol == dtls {
6115				test.config.Bugs.MaxHandshakeRecordLength = 2
6116				test.config.Bugs.PackHandshakeFragments = 20
6117				test.config.Bugs.PackHandshakeRecords = 1500
6118				test.config.Bugs.PackAppDataWithHandshake = true
6119			} else {
6120				test.config.Bugs.PackHandshakeFlight = true
6121			}
6122		}
6123		if config.implicitHandshake {
6124			test.name += "-ImplicitHandshake"
6125			test.flags = append(test.flags, "-implicit-handshake")
6126		}
6127		testCases = append(testCases, test)
6128	}
6129}
6130
6131func addDDoSCallbackTests() {
6132	// DDoS callback.
6133	for _, resume := range []bool{false, true} {
6134		suffix := "Resume"
6135		if resume {
6136			suffix = "No" + suffix
6137		}
6138
6139		testCases = append(testCases, testCase{
6140			testType: serverTest,
6141			name:     "Server-DDoS-OK-" + suffix,
6142			config: Config{
6143				MaxVersion: VersionTLS12,
6144			},
6145			flags:         []string{"-install-ddos-callback"},
6146			resumeSession: resume,
6147		})
6148		testCases = append(testCases, testCase{
6149			testType: serverTest,
6150			name:     "Server-DDoS-OK-" + suffix + "-TLS13",
6151			config: Config{
6152				MaxVersion: VersionTLS13,
6153			},
6154			flags:         []string{"-install-ddos-callback"},
6155			resumeSession: resume,
6156		})
6157
6158		failFlag := "-fail-ddos-callback"
6159		if resume {
6160			failFlag = "-on-resume-fail-ddos-callback"
6161		}
6162		testCases = append(testCases, testCase{
6163			testType: serverTest,
6164			name:     "Server-DDoS-Reject-" + suffix,
6165			config: Config{
6166				MaxVersion: VersionTLS12,
6167			},
6168			flags:              []string{"-install-ddos-callback", failFlag},
6169			resumeSession:      resume,
6170			shouldFail:         true,
6171			expectedError:      ":CONNECTION_REJECTED:",
6172			expectedLocalError: "remote error: internal error",
6173		})
6174		testCases = append(testCases, testCase{
6175			testType: serverTest,
6176			name:     "Server-DDoS-Reject-" + suffix + "-TLS13",
6177			config: Config{
6178				MaxVersion: VersionTLS13,
6179			},
6180			flags:              []string{"-install-ddos-callback", failFlag},
6181			resumeSession:      resume,
6182			shouldFail:         true,
6183			expectedError:      ":CONNECTION_REJECTED:",
6184			expectedLocalError: "remote error: internal error",
6185		})
6186	}
6187}
6188
6189func addVersionNegotiationTests() {
6190	for _, protocol := range []protocol{tls, dtls, quic} {
6191		for _, shimVers := range allVersions(protocol) {
6192			// Assemble flags to disable all newer versions on the shim.
6193			var flags []string
6194			for _, vers := range allVersions(protocol) {
6195				if vers.version > shimVers.version {
6196					flags = append(flags, vers.excludeFlag)
6197				}
6198			}
6199
6200			flags2 := []string{"-max-version", shimVers.shimFlag(protocol)}
6201
6202			// Test configuring the runner's maximum version.
6203			for _, runnerVers := range allVersions(protocol) {
6204				expectedVersion := shimVers.version
6205				if runnerVers.version < shimVers.version {
6206					expectedVersion = runnerVers.version
6207				}
6208
6209				suffix := shimVers.name + "-" + runnerVers.name
6210				suffix += "-" + protocol.String()
6211
6212				// Determine the expected initial record-layer versions.
6213				clientVers := shimVers.version
6214				if clientVers > VersionTLS10 {
6215					clientVers = VersionTLS10
6216				}
6217				clientVers = recordVersionToWire(clientVers, protocol)
6218				serverVers := expectedVersion
6219				if expectedVersion >= VersionTLS13 {
6220					serverVers = VersionTLS12
6221				}
6222				serverVers = recordVersionToWire(serverVers, protocol)
6223
6224				testCases = append(testCases, testCase{
6225					protocol: protocol,
6226					testType: clientTest,
6227					name:     "VersionNegotiation-Client-" + suffix,
6228					config: Config{
6229						MaxVersion: runnerVers.version,
6230						Bugs: ProtocolBugs{
6231							ExpectInitialRecordVersion: clientVers,
6232						},
6233					},
6234					flags: flags,
6235					expectations: connectionExpectations{
6236						version: expectedVersion,
6237					},
6238					// The version name check does not recognize the
6239					// |excludeFlag| construction in |flags|.
6240					skipVersionNameCheck: true,
6241				})
6242				testCases = append(testCases, testCase{
6243					protocol: protocol,
6244					testType: clientTest,
6245					name:     "VersionNegotiation-Client2-" + suffix,
6246					config: Config{
6247						MaxVersion: runnerVers.version,
6248						Bugs: ProtocolBugs{
6249							ExpectInitialRecordVersion: clientVers,
6250						},
6251					},
6252					flags: flags2,
6253					expectations: connectionExpectations{
6254						version: expectedVersion,
6255					},
6256				})
6257
6258				testCases = append(testCases, testCase{
6259					protocol: protocol,
6260					testType: serverTest,
6261					name:     "VersionNegotiation-Server-" + suffix,
6262					config: Config{
6263						MaxVersion: runnerVers.version,
6264						Bugs: ProtocolBugs{
6265							ExpectInitialRecordVersion: serverVers,
6266						},
6267					},
6268					flags: flags,
6269					expectations: connectionExpectations{
6270						version: expectedVersion,
6271					},
6272					// The version name check does not recognize the
6273					// |excludeFlag| construction in |flags|.
6274					skipVersionNameCheck: true,
6275				})
6276				testCases = append(testCases, testCase{
6277					protocol: protocol,
6278					testType: serverTest,
6279					name:     "VersionNegotiation-Server2-" + suffix,
6280					config: Config{
6281						MaxVersion: runnerVers.version,
6282						Bugs: ProtocolBugs{
6283							ExpectInitialRecordVersion: serverVers,
6284						},
6285					},
6286					flags: flags2,
6287					expectations: connectionExpectations{
6288						version: expectedVersion,
6289					},
6290				})
6291			}
6292		}
6293	}
6294
6295	// Test the version extension at all versions.
6296	for _, protocol := range []protocol{tls, dtls, quic} {
6297		for _, vers := range allVersions(protocol) {
6298			suffix := vers.name + "-" + protocol.String()
6299
6300			testCases = append(testCases, testCase{
6301				protocol: protocol,
6302				testType: serverTest,
6303				name:     "VersionNegotiationExtension-" + suffix,
6304				config: Config{
6305					Bugs: ProtocolBugs{
6306						SendSupportedVersions:      []uint16{0x1111, vers.wire(protocol), 0x2222},
6307						IgnoreTLS13DowngradeRandom: true,
6308					},
6309				},
6310				expectations: connectionExpectations{
6311					version: vers.version,
6312				},
6313			})
6314		}
6315	}
6316
6317	// If all versions are unknown, negotiation fails.
6318	testCases = append(testCases, testCase{
6319		testType: serverTest,
6320		name:     "NoSupportedVersions",
6321		config: Config{
6322			Bugs: ProtocolBugs{
6323				SendSupportedVersions: []uint16{0x1111},
6324			},
6325		},
6326		shouldFail:    true,
6327		expectedError: ":UNSUPPORTED_PROTOCOL:",
6328	})
6329	testCases = append(testCases, testCase{
6330		protocol: dtls,
6331		testType: serverTest,
6332		name:     "NoSupportedVersions-DTLS",
6333		config: Config{
6334			Bugs: ProtocolBugs{
6335				SendSupportedVersions: []uint16{0x1111},
6336			},
6337		},
6338		shouldFail:    true,
6339		expectedError: ":UNSUPPORTED_PROTOCOL:",
6340	})
6341
6342	testCases = append(testCases, testCase{
6343		testType: serverTest,
6344		name:     "ClientHelloVersionTooHigh",
6345		config: Config{
6346			MaxVersion: VersionTLS13,
6347			Bugs: ProtocolBugs{
6348				SendClientVersion:          0x0304,
6349				OmitSupportedVersions:      true,
6350				IgnoreTLS13DowngradeRandom: true,
6351			},
6352		},
6353		expectations: connectionExpectations{
6354			version: VersionTLS12,
6355		},
6356	})
6357
6358	testCases = append(testCases, testCase{
6359		testType: serverTest,
6360		name:     "ConflictingVersionNegotiation",
6361		config: Config{
6362			Bugs: ProtocolBugs{
6363				SendClientVersion:          VersionTLS12,
6364				SendSupportedVersions:      []uint16{VersionTLS11},
6365				IgnoreTLS13DowngradeRandom: true,
6366			},
6367		},
6368		// The extension takes precedence over the ClientHello version.
6369		expectations: connectionExpectations{
6370			version: VersionTLS11,
6371		},
6372	})
6373
6374	testCases = append(testCases, testCase{
6375		testType: serverTest,
6376		name:     "ConflictingVersionNegotiation-2",
6377		config: Config{
6378			Bugs: ProtocolBugs{
6379				SendClientVersion:          VersionTLS11,
6380				SendSupportedVersions:      []uint16{VersionTLS12},
6381				IgnoreTLS13DowngradeRandom: true,
6382			},
6383		},
6384		// The extension takes precedence over the ClientHello version.
6385		expectations: connectionExpectations{
6386			version: VersionTLS12,
6387		},
6388	})
6389
6390	// Test that TLS 1.2 isn't negotiated by the supported_versions extension in
6391	// the ServerHello.
6392	testCases = append(testCases, testCase{
6393		testType: clientTest,
6394		name:     "SupportedVersionSelection-TLS12",
6395		config: Config{
6396			MaxVersion: VersionTLS12,
6397			Bugs: ProtocolBugs{
6398				SendServerSupportedVersionExtension: VersionTLS12,
6399			},
6400		},
6401		shouldFail:    true,
6402		expectedError: ":UNEXPECTED_EXTENSION:",
6403	})
6404
6405	// Test that the maximum version is selected regardless of the
6406	// client-sent order.
6407	testCases = append(testCases, testCase{
6408		testType: serverTest,
6409		name:     "IgnoreClientVersionOrder",
6410		config: Config{
6411			Bugs: ProtocolBugs{
6412				SendSupportedVersions: []uint16{VersionTLS12, VersionTLS13},
6413			},
6414		},
6415		expectations: connectionExpectations{
6416			version: VersionTLS13,
6417		},
6418	})
6419
6420	// Test for version tolerance.
6421	testCases = append(testCases, testCase{
6422		testType: serverTest,
6423		name:     "MinorVersionTolerance",
6424		config: Config{
6425			Bugs: ProtocolBugs{
6426				SendClientVersion:          0x03ff,
6427				OmitSupportedVersions:      true,
6428				IgnoreTLS13DowngradeRandom: true,
6429			},
6430		},
6431		expectations: connectionExpectations{
6432			version: VersionTLS12,
6433		},
6434	})
6435	testCases = append(testCases, testCase{
6436		testType: serverTest,
6437		name:     "MajorVersionTolerance",
6438		config: Config{
6439			Bugs: ProtocolBugs{
6440				SendClientVersion:          0x0400,
6441				OmitSupportedVersions:      true,
6442				IgnoreTLS13DowngradeRandom: true,
6443			},
6444		},
6445		// TLS 1.3 must be negotiated with the supported_versions
6446		// extension, not ClientHello.version.
6447		expectations: connectionExpectations{
6448			version: VersionTLS12,
6449		},
6450	})
6451	testCases = append(testCases, testCase{
6452		testType: serverTest,
6453		name:     "VersionTolerance-TLS13",
6454		config: Config{
6455			Bugs: ProtocolBugs{
6456				// Although TLS 1.3 does not use
6457				// ClientHello.version, it still tolerates high
6458				// values there.
6459				SendClientVersion: 0x0400,
6460			},
6461		},
6462		expectations: connectionExpectations{
6463			version: VersionTLS13,
6464		},
6465	})
6466
6467	testCases = append(testCases, testCase{
6468		protocol: dtls,
6469		testType: serverTest,
6470		name:     "MinorVersionTolerance-DTLS",
6471		config: Config{
6472			Bugs: ProtocolBugs{
6473				SendClientVersion:     0xfe00,
6474				OmitSupportedVersions: true,
6475			},
6476		},
6477		expectations: connectionExpectations{
6478			version: VersionTLS12,
6479		},
6480	})
6481	testCases = append(testCases, testCase{
6482		protocol: dtls,
6483		testType: serverTest,
6484		name:     "MajorVersionTolerance-DTLS",
6485		config: Config{
6486			Bugs: ProtocolBugs{
6487				SendClientVersion:     0xfdff,
6488				OmitSupportedVersions: true,
6489			},
6490		},
6491		expectations: connectionExpectations{
6492			version: VersionTLS12,
6493		},
6494	})
6495
6496	// Test that versions below 3.0 are rejected.
6497	testCases = append(testCases, testCase{
6498		testType: serverTest,
6499		name:     "VersionTooLow",
6500		config: Config{
6501			Bugs: ProtocolBugs{
6502				SendClientVersion:     0x0200,
6503				OmitSupportedVersions: true,
6504			},
6505		},
6506		shouldFail:    true,
6507		expectedError: ":UNSUPPORTED_PROTOCOL:",
6508	})
6509	testCases = append(testCases, testCase{
6510		protocol: dtls,
6511		testType: serverTest,
6512		name:     "VersionTooLow-DTLS",
6513		config: Config{
6514			Bugs: ProtocolBugs{
6515				SendClientVersion: 0xffff,
6516			},
6517		},
6518		shouldFail:    true,
6519		expectedError: ":UNSUPPORTED_PROTOCOL:",
6520	})
6521
6522	testCases = append(testCases, testCase{
6523		name: "ServerBogusVersion",
6524		config: Config{
6525			Bugs: ProtocolBugs{
6526				SendServerHelloVersion: 0x1234,
6527			},
6528		},
6529		shouldFail:    true,
6530		expectedError: ":UNSUPPORTED_PROTOCOL:",
6531	})
6532
6533	// Test TLS 1.3's downgrade signal.
6534	var downgradeTests = []struct {
6535		name            string
6536		version         uint16
6537		clientShimError string
6538	}{
6539		{"TLS12", VersionTLS12, "tls: downgrade from TLS 1.3 detected"},
6540		{"TLS11", VersionTLS11, "tls: downgrade from TLS 1.2 detected"},
6541		// TLS 1.0 does not have a dedicated value.
6542		{"TLS10", VersionTLS10, "tls: downgrade from TLS 1.2 detected"},
6543	}
6544
6545	for _, test := range downgradeTests {
6546		// The client should enforce the downgrade sentinel.
6547		testCases = append(testCases, testCase{
6548			name: "Downgrade-" + test.name + "-Client",
6549			config: Config{
6550				Bugs: ProtocolBugs{
6551					NegotiateVersion: test.version,
6552				},
6553			},
6554			expectations: connectionExpectations{
6555				version: test.version,
6556			},
6557			shouldFail:         true,
6558			expectedError:      ":TLS13_DOWNGRADE:",
6559			expectedLocalError: "remote error: illegal parameter",
6560		})
6561
6562		// The server should emit the downgrade signal.
6563		testCases = append(testCases, testCase{
6564			testType: serverTest,
6565			name:     "Downgrade-" + test.name + "-Server",
6566			config: Config{
6567				Bugs: ProtocolBugs{
6568					SendSupportedVersions: []uint16{test.version},
6569				},
6570			},
6571			expectations: connectionExpectations{
6572				version: test.version,
6573			},
6574			shouldFail:         true,
6575			expectedLocalError: test.clientShimError,
6576		})
6577	}
6578
6579	// SSL 3.0 support has been removed. Test that the shim does not
6580	// support it.
6581	testCases = append(testCases, testCase{
6582		name: "NoSSL3-Client",
6583		config: Config{
6584			MinVersion: VersionSSL30,
6585			MaxVersion: VersionSSL30,
6586		},
6587		shouldFail:         true,
6588		expectedLocalError: "tls: client did not offer any supported protocol versions",
6589	})
6590	testCases = append(testCases, testCase{
6591		name: "NoSSL3-Client-Unsolicited",
6592		config: Config{
6593			MinVersion: VersionSSL30,
6594			MaxVersion: VersionSSL30,
6595			Bugs: ProtocolBugs{
6596				// The above test asserts the client does not
6597				// offer SSL 3.0 in the supported_versions
6598				// list. Additionally assert that it rejects an
6599				// unsolicited SSL 3.0 ServerHello.
6600				NegotiateVersion: VersionSSL30,
6601			},
6602		},
6603		shouldFail:         true,
6604		expectedError:      ":UNSUPPORTED_PROTOCOL:",
6605		expectedLocalError: "remote error: protocol version not supported",
6606	})
6607	testCases = append(testCases, testCase{
6608		testType: serverTest,
6609		name:     "NoSSL3-Server",
6610		config: Config{
6611			MinVersion: VersionSSL30,
6612			MaxVersion: VersionSSL30,
6613		},
6614		shouldFail:         true,
6615		expectedError:      ":UNSUPPORTED_PROTOCOL:",
6616		expectedLocalError: "remote error: protocol version not supported",
6617	})
6618}
6619
6620func addMinimumVersionTests() {
6621	for _, protocol := range []protocol{tls, dtls, quic} {
6622		for _, shimVers := range allVersions(protocol) {
6623			// Assemble flags to disable all older versions on the shim.
6624			var flags []string
6625			for _, vers := range allVersions(protocol) {
6626				if vers.version < shimVers.version {
6627					flags = append(flags, vers.excludeFlag)
6628				}
6629			}
6630
6631			flags2 := []string{"-min-version", shimVers.shimFlag(protocol)}
6632
6633			for _, runnerVers := range allVersions(protocol) {
6634				suffix := shimVers.name + "-" + runnerVers.name
6635				suffix += "-" + protocol.String()
6636
6637				var expectedVersion uint16
6638				var shouldFail bool
6639				var expectedError, expectedLocalError string
6640				if runnerVers.version >= shimVers.version {
6641					expectedVersion = runnerVers.version
6642				} else {
6643					shouldFail = true
6644					expectedError = ":UNSUPPORTED_PROTOCOL:"
6645					expectedLocalError = "remote error: protocol version not supported"
6646				}
6647
6648				testCases = append(testCases, testCase{
6649					protocol: protocol,
6650					testType: clientTest,
6651					name:     "MinimumVersion-Client-" + suffix,
6652					config: Config{
6653						MaxVersion: runnerVers.version,
6654						Bugs: ProtocolBugs{
6655							// Ensure the server does not decline to
6656							// select a version (versions extension) or
6657							// cipher (some ciphers depend on versions).
6658							NegotiateVersion:            runnerVers.wire(protocol),
6659							IgnorePeerCipherPreferences: shouldFail,
6660						},
6661					},
6662					flags: flags,
6663					expectations: connectionExpectations{
6664						version: expectedVersion,
6665					},
6666					shouldFail:         shouldFail,
6667					expectedError:      expectedError,
6668					expectedLocalError: expectedLocalError,
6669					// The version name check does not recognize the
6670					// |excludeFlag| construction in |flags|.
6671					skipVersionNameCheck: true,
6672				})
6673				testCases = append(testCases, testCase{
6674					protocol: protocol,
6675					testType: clientTest,
6676					name:     "MinimumVersion-Client2-" + suffix,
6677					config: Config{
6678						MaxVersion: runnerVers.version,
6679						Bugs: ProtocolBugs{
6680							// Ensure the server does not decline to
6681							// select a version (versions extension) or
6682							// cipher (some ciphers depend on versions).
6683							NegotiateVersion:            runnerVers.wire(protocol),
6684							IgnorePeerCipherPreferences: shouldFail,
6685						},
6686					},
6687					flags: flags2,
6688					expectations: connectionExpectations{
6689						version: expectedVersion,
6690					},
6691					shouldFail:         shouldFail,
6692					expectedError:      expectedError,
6693					expectedLocalError: expectedLocalError,
6694				})
6695
6696				testCases = append(testCases, testCase{
6697					protocol: protocol,
6698					testType: serverTest,
6699					name:     "MinimumVersion-Server-" + suffix,
6700					config: Config{
6701						MaxVersion: runnerVers.version,
6702					},
6703					flags: flags,
6704					expectations: connectionExpectations{
6705						version: expectedVersion,
6706					},
6707					shouldFail:         shouldFail,
6708					expectedError:      expectedError,
6709					expectedLocalError: expectedLocalError,
6710					// The version name check does not recognize the
6711					// |excludeFlag| construction in |flags|.
6712					skipVersionNameCheck: true,
6713				})
6714				testCases = append(testCases, testCase{
6715					protocol: protocol,
6716					testType: serverTest,
6717					name:     "MinimumVersion-Server2-" + suffix,
6718					config: Config{
6719						MaxVersion: runnerVers.version,
6720					},
6721					flags: flags2,
6722					expectations: connectionExpectations{
6723						version: expectedVersion,
6724					},
6725					shouldFail:         shouldFail,
6726					expectedError:      expectedError,
6727					expectedLocalError: expectedLocalError,
6728				})
6729			}
6730		}
6731	}
6732}
6733
6734func addExtensionTests() {
6735	exampleCertificate := generateSingleCertChain(&x509.Certificate{
6736		SerialNumber: big.NewInt(57005),
6737		Subject: pkix.Name{
6738			CommonName: "test cert",
6739		},
6740		NotBefore:             time.Now().Add(-time.Hour),
6741		NotAfter:              time.Now().Add(time.Hour),
6742		DNSNames:              []string{"example.com"},
6743		IsCA:                  true,
6744		BasicConstraintsValid: true,
6745	}, &ecdsaP256Key)
6746
6747	// Repeat extensions tests at all versions.
6748	for _, protocol := range []protocol{tls, dtls, quic} {
6749		for _, ver := range allVersions(protocol) {
6750			suffix := fmt.Sprintf("%s-%s", protocol.String(), ver.name)
6751
6752			// Test that duplicate extensions are rejected.
6753			testCases = append(testCases, testCase{
6754				protocol: protocol,
6755				testType: clientTest,
6756				name:     "DuplicateExtensionClient-" + suffix,
6757				config: Config{
6758					MaxVersion: ver.version,
6759					Bugs: ProtocolBugs{
6760						DuplicateExtension: true,
6761					},
6762				},
6763				shouldFail:         true,
6764				expectedLocalError: "remote error: error decoding message",
6765			})
6766			testCases = append(testCases, testCase{
6767				protocol: protocol,
6768				testType: serverTest,
6769				name:     "DuplicateExtensionServer-" + suffix,
6770				config: Config{
6771					MaxVersion: ver.version,
6772					Bugs: ProtocolBugs{
6773						DuplicateExtension: true,
6774					},
6775				},
6776				shouldFail:         true,
6777				expectedLocalError: "remote error: error decoding message",
6778			})
6779
6780			// Test SNI.
6781			testCases = append(testCases, testCase{
6782				protocol: protocol,
6783				testType: clientTest,
6784				name:     "ServerNameExtensionClient-" + suffix,
6785				config: Config{
6786					MaxVersion: ver.version,
6787					Bugs: ProtocolBugs{
6788						ExpectServerName: "example.com",
6789					},
6790					Credential: &exampleCertificate,
6791				},
6792				flags: []string{"-host-name", "example.com"},
6793			})
6794			testCases = append(testCases, testCase{
6795				protocol: protocol,
6796				testType: clientTest,
6797				name:     "ServerNameExtensionClientMismatch-" + suffix,
6798				config: Config{
6799					MaxVersion: ver.version,
6800					Bugs: ProtocolBugs{
6801						ExpectServerName: "mismatch.com",
6802					},
6803				},
6804				flags:              []string{"-host-name", "example.com"},
6805				shouldFail:         true,
6806				expectedLocalError: "tls: unexpected server name",
6807			})
6808			testCases = append(testCases, testCase{
6809				protocol: protocol,
6810				testType: clientTest,
6811				name:     "ServerNameExtensionClientMissing-" + suffix,
6812				config: Config{
6813					MaxVersion: ver.version,
6814					Bugs: ProtocolBugs{
6815						ExpectServerName: "missing.com",
6816					},
6817				},
6818				shouldFail:         true,
6819				expectedLocalError: "tls: unexpected server name",
6820			})
6821			testCases = append(testCases, testCase{
6822				protocol: protocol,
6823				testType: clientTest,
6824				name:     "TolerateServerNameAck-" + suffix,
6825				config: Config{
6826					MaxVersion: ver.version,
6827					Bugs: ProtocolBugs{
6828						SendServerNameAck: true,
6829					},
6830					Credential: &exampleCertificate,
6831				},
6832				flags:         []string{"-host-name", "example.com"},
6833				resumeSession: true,
6834			})
6835			testCases = append(testCases, testCase{
6836				protocol: protocol,
6837				testType: clientTest,
6838				name:     "UnsolicitedServerNameAck-" + suffix,
6839				config: Config{
6840					MaxVersion: ver.version,
6841					Bugs: ProtocolBugs{
6842						SendServerNameAck: true,
6843					},
6844				},
6845				shouldFail:         true,
6846				expectedError:      ":UNEXPECTED_EXTENSION:",
6847				expectedLocalError: "remote error: unsupported extension",
6848			})
6849			testCases = append(testCases, testCase{
6850				protocol: protocol,
6851				testType: serverTest,
6852				name:     "ServerNameExtensionServer-" + suffix,
6853				config: Config{
6854					MaxVersion: ver.version,
6855					ServerName: "example.com",
6856				},
6857				flags:         []string{"-expect-server-name", "example.com"},
6858				resumeSession: true,
6859			})
6860
6861			// Test ALPN.
6862			testCases = append(testCases, testCase{
6863				protocol:           protocol,
6864				testType:           clientTest,
6865				skipQUICALPNConfig: true,
6866				name:               "ALPNClient-" + suffix,
6867				config: Config{
6868					MaxVersion: ver.version,
6869					NextProtos: []string{"foo"},
6870				},
6871				flags: []string{
6872					"-advertise-alpn", "\x03foo\x03bar\x03baz",
6873					"-expect-alpn", "foo",
6874				},
6875				expectations: connectionExpectations{
6876					nextProto:     "foo",
6877					nextProtoType: alpn,
6878				},
6879				resumeSession: true,
6880			})
6881			testCases = append(testCases, testCase{
6882				protocol:           protocol,
6883				testType:           clientTest,
6884				skipQUICALPNConfig: true,
6885				name:               "ALPNClient-RejectUnknown-" + suffix,
6886				config: Config{
6887					MaxVersion: ver.version,
6888					Bugs: ProtocolBugs{
6889						SendALPN: "baz",
6890					},
6891				},
6892				flags: []string{
6893					"-advertise-alpn", "\x03foo\x03bar",
6894				},
6895				shouldFail:         true,
6896				expectedError:      ":INVALID_ALPN_PROTOCOL:",
6897				expectedLocalError: "remote error: illegal parameter",
6898			})
6899			testCases = append(testCases, testCase{
6900				protocol:           protocol,
6901				testType:           clientTest,
6902				skipQUICALPNConfig: true,
6903				name:               "ALPNClient-AllowUnknown-" + suffix,
6904				config: Config{
6905					MaxVersion: ver.version,
6906					Bugs: ProtocolBugs{
6907						SendALPN: "baz",
6908					},
6909				},
6910				flags: []string{
6911					"-advertise-alpn", "\x03foo\x03bar",
6912					"-allow-unknown-alpn-protos",
6913					"-expect-alpn", "baz",
6914				},
6915			})
6916			testCases = append(testCases, testCase{
6917				protocol:           protocol,
6918				testType:           serverTest,
6919				skipQUICALPNConfig: true,
6920				name:               "ALPNServer-" + suffix,
6921				config: Config{
6922					MaxVersion: ver.version,
6923					NextProtos: []string{"foo", "bar", "baz"},
6924				},
6925				flags: []string{
6926					"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
6927					"-select-alpn", "foo",
6928				},
6929				expectations: connectionExpectations{
6930					nextProto:     "foo",
6931					nextProtoType: alpn,
6932				},
6933				resumeSession: true,
6934			})
6935
6936			var shouldDeclineALPNFail bool
6937			var declineALPNError, declineALPNLocalError string
6938			if protocol == quic {
6939				// ALPN is mandatory in QUIC.
6940				shouldDeclineALPNFail = true
6941				declineALPNError = ":NO_APPLICATION_PROTOCOL:"
6942				declineALPNLocalError = "remote error: no application protocol"
6943			}
6944			testCases = append(testCases, testCase{
6945				protocol:           protocol,
6946				testType:           serverTest,
6947				skipQUICALPNConfig: true,
6948				name:               "ALPNServer-Decline-" + suffix,
6949				config: Config{
6950					MaxVersion: ver.version,
6951					NextProtos: []string{"foo", "bar", "baz"},
6952				},
6953				flags: []string{"-decline-alpn"},
6954				expectations: connectionExpectations{
6955					noNextProto: true,
6956				},
6957				resumeSession:      true,
6958				shouldFail:         shouldDeclineALPNFail,
6959				expectedError:      declineALPNError,
6960				expectedLocalError: declineALPNLocalError,
6961			})
6962
6963			testCases = append(testCases, testCase{
6964				protocol:           protocol,
6965				testType:           serverTest,
6966				skipQUICALPNConfig: true,
6967				name:               "ALPNServer-Reject-" + suffix,
6968				config: Config{
6969					MaxVersion: ver.version,
6970					NextProtos: []string{"foo", "bar", "baz"},
6971				},
6972				flags:              []string{"-reject-alpn"},
6973				shouldFail:         true,
6974				expectedError:      ":NO_APPLICATION_PROTOCOL:",
6975				expectedLocalError: "remote error: no application protocol",
6976			})
6977
6978			// Test that the server implementation catches itself if the
6979			// callback tries to return an invalid empty ALPN protocol.
6980			testCases = append(testCases, testCase{
6981				protocol:           protocol,
6982				testType:           serverTest,
6983				skipQUICALPNConfig: true,
6984				name:               "ALPNServer-SelectEmpty-" + suffix,
6985				config: Config{
6986					MaxVersion: ver.version,
6987					NextProtos: []string{"foo", "bar", "baz"},
6988				},
6989				flags: []string{
6990					"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
6991					"-select-empty-alpn",
6992				},
6993				shouldFail:         true,
6994				expectedLocalError: "remote error: internal error",
6995				expectedError:      ":INVALID_ALPN_PROTOCOL:",
6996			})
6997
6998			// Test ALPN in async mode as well to ensure that extensions callbacks are only
6999			// called once.
7000			testCases = append(testCases, testCase{
7001				protocol:           protocol,
7002				testType:           serverTest,
7003				skipQUICALPNConfig: true,
7004				name:               "ALPNServer-Async-" + suffix,
7005				config: Config{
7006					MaxVersion: ver.version,
7007					NextProtos: []string{"foo", "bar", "baz"},
7008					// Prior to TLS 1.3, exercise the asynchronous session callback.
7009					SessionTicketsDisabled: ver.version < VersionTLS13,
7010				},
7011				flags: []string{
7012					"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
7013					"-select-alpn", "foo",
7014					"-async",
7015				},
7016				expectations: connectionExpectations{
7017					nextProto:     "foo",
7018					nextProtoType: alpn,
7019				},
7020				resumeSession: true,
7021			})
7022
7023			var emptyString string
7024			testCases = append(testCases, testCase{
7025				protocol:           protocol,
7026				testType:           clientTest,
7027				skipQUICALPNConfig: true,
7028				name:               "ALPNClient-EmptyProtocolName-" + suffix,
7029				config: Config{
7030					MaxVersion: ver.version,
7031					NextProtos: []string{""},
7032					Bugs: ProtocolBugs{
7033						// A server returning an empty ALPN protocol
7034						// should be rejected.
7035						ALPNProtocol: &emptyString,
7036					},
7037				},
7038				flags: []string{
7039					"-advertise-alpn", "\x03foo",
7040				},
7041				shouldFail:    true,
7042				expectedError: ":PARSE_TLSEXT:",
7043			})
7044			testCases = append(testCases, testCase{
7045				protocol:           protocol,
7046				testType:           serverTest,
7047				skipQUICALPNConfig: true,
7048				name:               "ALPNServer-EmptyProtocolName-" + suffix,
7049				config: Config{
7050					MaxVersion: ver.version,
7051					// A ClientHello containing an empty ALPN protocol
7052					// should be rejected.
7053					NextProtos: []string{"foo", "", "baz"},
7054				},
7055				flags: []string{
7056					"-select-alpn", "foo",
7057				},
7058				shouldFail:    true,
7059				expectedError: ":PARSE_TLSEXT:",
7060			})
7061
7062			// Test NPN and the interaction with ALPN.
7063			if ver.version < VersionTLS13 && protocol == tls {
7064				// Test that the server prefers ALPN over NPN.
7065				testCases = append(testCases, testCase{
7066					protocol: protocol,
7067					testType: serverTest,
7068					name:     "ALPNServer-Preferred-" + suffix,
7069					config: Config{
7070						MaxVersion: ver.version,
7071						NextProtos: []string{"foo", "bar", "baz"},
7072					},
7073					flags: []string{
7074						"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
7075						"-select-alpn", "foo",
7076						"-advertise-npn", "\x03foo\x03bar\x03baz",
7077					},
7078					expectations: connectionExpectations{
7079						nextProto:     "foo",
7080						nextProtoType: alpn,
7081					},
7082					resumeSession: true,
7083				})
7084				testCases = append(testCases, testCase{
7085					protocol: protocol,
7086					testType: serverTest,
7087					name:     "ALPNServer-Preferred-Swapped-" + suffix,
7088					config: Config{
7089						MaxVersion: ver.version,
7090						NextProtos: []string{"foo", "bar", "baz"},
7091						Bugs: ProtocolBugs{
7092							SwapNPNAndALPN: true,
7093						},
7094					},
7095					flags: []string{
7096						"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
7097						"-select-alpn", "foo",
7098						"-advertise-npn", "\x03foo\x03bar\x03baz",
7099					},
7100					expectations: connectionExpectations{
7101						nextProto:     "foo",
7102						nextProtoType: alpn,
7103					},
7104					resumeSession: true,
7105				})
7106
7107				// Test that negotiating both NPN and ALPN is forbidden.
7108				testCases = append(testCases, testCase{
7109					protocol: protocol,
7110					name:     "NegotiateALPNAndNPN-" + suffix,
7111					config: Config{
7112						MaxVersion: ver.version,
7113						NextProtos: []string{"foo", "bar", "baz"},
7114						Bugs: ProtocolBugs{
7115							NegotiateALPNAndNPN: true,
7116						},
7117					},
7118					flags: []string{
7119						"-advertise-alpn", "\x03foo",
7120						"-select-next-proto", "foo",
7121					},
7122					shouldFail:    true,
7123					expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
7124				})
7125				testCases = append(testCases, testCase{
7126					protocol: protocol,
7127					name:     "NegotiateALPNAndNPN-Swapped-" + suffix,
7128					config: Config{
7129						MaxVersion: ver.version,
7130						NextProtos: []string{"foo", "bar", "baz"},
7131						Bugs: ProtocolBugs{
7132							NegotiateALPNAndNPN: true,
7133							SwapNPNAndALPN:      true,
7134						},
7135					},
7136					flags: []string{
7137						"-advertise-alpn", "\x03foo",
7138						"-select-next-proto", "foo",
7139					},
7140					shouldFail:    true,
7141					expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
7142				})
7143			}
7144
7145			// Test missing ALPN in QUIC
7146			if protocol == quic {
7147				testCases = append(testCases, testCase{
7148					testType: clientTest,
7149					protocol: protocol,
7150					name:     "Client-ALPNMissingFromConfig-" + suffix,
7151					config: Config{
7152						MinVersion: ver.version,
7153						MaxVersion: ver.version,
7154					},
7155					skipQUICALPNConfig: true,
7156					shouldFail:         true,
7157					expectedError:      ":NO_APPLICATION_PROTOCOL:",
7158				})
7159				testCases = append(testCases, testCase{
7160					testType: clientTest,
7161					protocol: protocol,
7162					name:     "Client-ALPNMissing-" + suffix,
7163					config: Config{
7164						MinVersion: ver.version,
7165						MaxVersion: ver.version,
7166					},
7167					flags: []string{
7168						"-advertise-alpn", "\x03foo",
7169					},
7170					skipQUICALPNConfig: true,
7171					shouldFail:         true,
7172					expectedError:      ":NO_APPLICATION_PROTOCOL:",
7173					expectedLocalError: "remote error: no application protocol",
7174				})
7175				testCases = append(testCases, testCase{
7176					testType: serverTest,
7177					protocol: protocol,
7178					name:     "Server-ALPNMissing-" + suffix,
7179					config: Config{
7180						MinVersion: ver.version,
7181						MaxVersion: ver.version,
7182					},
7183					skipQUICALPNConfig: true,
7184					shouldFail:         true,
7185					expectedError:      ":NO_APPLICATION_PROTOCOL:",
7186					expectedLocalError: "remote error: no application protocol",
7187				})
7188				testCases = append(testCases, testCase{
7189					testType: serverTest,
7190					protocol: protocol,
7191					name:     "Server-ALPNMismatch-" + suffix,
7192					config: Config{
7193						MinVersion: ver.version,
7194						MaxVersion: ver.version,
7195						NextProtos: []string{"foo"},
7196					},
7197					flags: []string{
7198						"-decline-alpn",
7199					},
7200					skipQUICALPNConfig: true,
7201					shouldFail:         true,
7202					expectedError:      ":NO_APPLICATION_PROTOCOL:",
7203					expectedLocalError: "remote error: no application protocol",
7204				})
7205			}
7206
7207			// Test ALPS.
7208			if ver.version >= VersionTLS13 {
7209				// Test basic client with different ALPS codepoint.
7210				for _, alpsCodePoint := range []ALPSUseCodepoint{ALPSUseCodepointNew, ALPSUseCodepointOld} {
7211					flags := []string{}
7212					expectations := connectionExpectations{
7213						peerApplicationSettingsOld: []byte("shim1"),
7214					}
7215					resumeExpectations := &connectionExpectations{
7216						peerApplicationSettingsOld: []byte("shim2"),
7217					}
7218
7219					if alpsCodePoint == ALPSUseCodepointNew {
7220						flags = append(flags, "-alps-use-new-codepoint")
7221						expectations = connectionExpectations{
7222							peerApplicationSettings: []byte("shim1"),
7223						}
7224						resumeExpectations = &connectionExpectations{
7225							peerApplicationSettings: []byte("shim2"),
7226						}
7227					}
7228
7229					flags = append(flags,
7230						"-advertise-alpn", "\x05proto",
7231						"-expect-alpn", "proto",
7232						"-on-initial-application-settings", "proto,shim1",
7233						"-on-initial-expect-peer-application-settings", "runner1",
7234						"-on-resume-application-settings", "proto,shim2",
7235						"-on-resume-expect-peer-application-settings", "runner2")
7236
7237					// Test that server can negotiate ALPS, including different values
7238					// on resumption.
7239					testCases = append(testCases, testCase{
7240						protocol:           protocol,
7241						testType:           clientTest,
7242						name:               fmt.Sprintf("ALPS-Basic-Client-%s-%s", alpsCodePoint, suffix),
7243						skipQUICALPNConfig: true,
7244						config: Config{
7245							MaxVersion:          ver.version,
7246							NextProtos:          []string{"proto"},
7247							ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
7248							ALPSUseNewCodepoint: alpsCodePoint,
7249						},
7250						resumeConfig: &Config{
7251							MaxVersion:          ver.version,
7252							NextProtos:          []string{"proto"},
7253							ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
7254							ALPSUseNewCodepoint: alpsCodePoint,
7255						},
7256						resumeSession:      true,
7257						expectations:       expectations,
7258						resumeExpectations: resumeExpectations,
7259						flags:              flags,
7260					})
7261
7262					// Test basic server with different ALPS codepoint.
7263					flags = []string{}
7264					expectations = connectionExpectations{
7265						peerApplicationSettingsOld: []byte("shim1"),
7266					}
7267					resumeExpectations = &connectionExpectations{
7268						peerApplicationSettingsOld: []byte("shim2"),
7269					}
7270
7271					if alpsCodePoint == ALPSUseCodepointNew {
7272						flags = append(flags, "-alps-use-new-codepoint")
7273						expectations = connectionExpectations{
7274							peerApplicationSettings: []byte("shim1"),
7275						}
7276						resumeExpectations = &connectionExpectations{
7277							peerApplicationSettings: []byte("shim2"),
7278						}
7279					}
7280
7281					flags = append(flags,
7282						"-select-alpn", "proto",
7283						"-on-initial-application-settings", "proto,shim1",
7284						"-on-initial-expect-peer-application-settings", "runner1",
7285						"-on-resume-application-settings", "proto,shim2",
7286						"-on-resume-expect-peer-application-settings", "runner2")
7287
7288					// Test that server can negotiate ALPS, including different values
7289					// on resumption.
7290					testCases = append(testCases, testCase{
7291						protocol:           protocol,
7292						testType:           serverTest,
7293						name:               fmt.Sprintf("ALPS-Basic-Server-%s-%s", alpsCodePoint, suffix),
7294						skipQUICALPNConfig: true,
7295						config: Config{
7296							MaxVersion:          ver.version,
7297							NextProtos:          []string{"proto"},
7298							ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
7299							ALPSUseNewCodepoint: alpsCodePoint,
7300						},
7301						resumeConfig: &Config{
7302							MaxVersion:          ver.version,
7303							NextProtos:          []string{"proto"},
7304							ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
7305							ALPSUseNewCodepoint: alpsCodePoint,
7306						},
7307						resumeSession:      true,
7308						expectations:       expectations,
7309						resumeExpectations: resumeExpectations,
7310						flags:              flags,
7311					})
7312
7313					// Try different ALPS codepoint for all the existing tests.
7314					alpsFlags := []string{}
7315					expectations = connectionExpectations{
7316						peerApplicationSettingsOld: []byte("shim1"),
7317					}
7318					resumeExpectations = &connectionExpectations{
7319						peerApplicationSettingsOld: []byte("shim2"),
7320					}
7321					if alpsCodePoint == ALPSUseCodepointNew {
7322						alpsFlags = append(alpsFlags, "-alps-use-new-codepoint")
7323						expectations = connectionExpectations{
7324							peerApplicationSettings: []byte("shim1"),
7325						}
7326						resumeExpectations = &connectionExpectations{
7327							peerApplicationSettings: []byte("shim2"),
7328						}
7329					}
7330
7331					// Test that the server can defer its ALPS configuration to the ALPN
7332					// selection callback.
7333					testCases = append(testCases, testCase{
7334						protocol:           protocol,
7335						testType:           serverTest,
7336						name:               fmt.Sprintf("ALPS-Basic-Server-Defer-%s-%s", alpsCodePoint, suffix),
7337						skipQUICALPNConfig: true,
7338						config: Config{
7339							MaxVersion:          ver.version,
7340							NextProtos:          []string{"proto"},
7341							ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
7342							ALPSUseNewCodepoint: alpsCodePoint,
7343						},
7344						resumeConfig: &Config{
7345							MaxVersion:          ver.version,
7346							NextProtos:          []string{"proto"},
7347							ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
7348							ALPSUseNewCodepoint: alpsCodePoint,
7349						},
7350						resumeSession:      true,
7351						expectations:       expectations,
7352						resumeExpectations: resumeExpectations,
7353						flags: append([]string{
7354							"-select-alpn", "proto",
7355							"-defer-alps",
7356							"-on-initial-application-settings", "proto,shim1",
7357							"-on-initial-expect-peer-application-settings", "runner1",
7358							"-on-resume-application-settings", "proto,shim2",
7359							"-on-resume-expect-peer-application-settings", "runner2",
7360						}, alpsFlags...),
7361					})
7362
7363					expectations = connectionExpectations{
7364						peerApplicationSettingsOld: []byte{},
7365					}
7366					if alpsCodePoint == ALPSUseCodepointNew {
7367						expectations = connectionExpectations{
7368							peerApplicationSettings: []byte{},
7369						}
7370					}
7371					// Test the client and server correctly handle empty settings.
7372					testCases = append(testCases, testCase{
7373						protocol:           protocol,
7374						testType:           clientTest,
7375						name:               fmt.Sprintf("ALPS-Empty-Client-%s-%s", alpsCodePoint, suffix),
7376						skipQUICALPNConfig: true,
7377						config: Config{
7378							MaxVersion:          ver.version,
7379							NextProtos:          []string{"proto"},
7380							ApplicationSettings: map[string][]byte{"proto": []byte{}},
7381							ALPSUseNewCodepoint: alpsCodePoint,
7382						},
7383						resumeSession: true,
7384						expectations:  expectations,
7385						flags: append([]string{
7386							"-advertise-alpn", "\x05proto",
7387							"-expect-alpn", "proto",
7388							"-application-settings", "proto,",
7389							"-expect-peer-application-settings", "",
7390						}, alpsFlags...),
7391					})
7392					testCases = append(testCases, testCase{
7393						protocol:           protocol,
7394						testType:           serverTest,
7395						name:               fmt.Sprintf("ALPS-Empty-Server-%s-%s", alpsCodePoint, suffix),
7396						skipQUICALPNConfig: true,
7397						config: Config{
7398							MaxVersion:          ver.version,
7399							NextProtos:          []string{"proto"},
7400							ApplicationSettings: map[string][]byte{"proto": []byte{}},
7401							ALPSUseNewCodepoint: alpsCodePoint,
7402						},
7403						resumeSession: true,
7404						expectations:  expectations,
7405						flags: append([]string{
7406							"-select-alpn", "proto",
7407							"-application-settings", "proto,",
7408							"-expect-peer-application-settings", "",
7409						}, alpsFlags...),
7410					})
7411
7412					bugs := ProtocolBugs{
7413						AlwaysNegotiateApplicationSettingsOld: true,
7414					}
7415					if alpsCodePoint == ALPSUseCodepointNew {
7416						bugs = ProtocolBugs{
7417							AlwaysNegotiateApplicationSettingsNew: true,
7418						}
7419					}
7420					// Test the client rejects application settings from the server on
7421					// protocols it doesn't have them.
7422					testCases = append(testCases, testCase{
7423						protocol:           protocol,
7424						testType:           clientTest,
7425						name:               fmt.Sprintf("ALPS-UnsupportedProtocol-Client-%s-%s", alpsCodePoint, suffix),
7426						skipQUICALPNConfig: true,
7427						config: Config{
7428							MaxVersion:          ver.version,
7429							NextProtos:          []string{"proto1"},
7430							ApplicationSettings: map[string][]byte{"proto1": []byte("runner")},
7431							Bugs:                bugs,
7432							ALPSUseNewCodepoint: alpsCodePoint,
7433						},
7434						// The client supports ALPS with "proto2", but not "proto1".
7435						flags: append([]string{
7436							"-advertise-alpn", "\x06proto1\x06proto2",
7437							"-application-settings", "proto2,shim",
7438							"-expect-alpn", "proto1",
7439						}, alpsFlags...),
7440						// The server sends ALPS with "proto1", which is invalid.
7441						shouldFail:         true,
7442						expectedError:      ":INVALID_ALPN_PROTOCOL:",
7443						expectedLocalError: "remote error: illegal parameter",
7444					})
7445
7446					// Test client rejects application settings from the server when
7447					// server sends the wrong ALPS codepoint.
7448					bugs = ProtocolBugs{
7449						AlwaysNegotiateApplicationSettingsOld: true,
7450					}
7451					if alpsCodePoint == ALPSUseCodepointOld {
7452						bugs = ProtocolBugs{
7453							AlwaysNegotiateApplicationSettingsNew: true,
7454						}
7455					}
7456
7457					testCases = append(testCases, testCase{
7458						protocol:           protocol,
7459						testType:           clientTest,
7460						name:               fmt.Sprintf("ALPS-WrongServerCodepoint-Client-%s-%s", alpsCodePoint, suffix),
7461						skipQUICALPNConfig: true,
7462						config: Config{
7463							MaxVersion:          ver.version,
7464							NextProtos:          []string{"proto"},
7465							ApplicationSettings: map[string][]byte{"proto": []byte{}},
7466							Bugs:                bugs,
7467							ALPSUseNewCodepoint: alpsCodePoint,
7468						},
7469						flags: append([]string{
7470							"-advertise-alpn", "\x05proto",
7471							"-expect-alpn", "proto",
7472							"-application-settings", "proto,",
7473							"-expect-peer-application-settings", "",
7474						}, alpsFlags...),
7475						shouldFail:         true,
7476						expectedError:      ":UNEXPECTED_EXTENSION:",
7477						expectedLocalError: "remote error: unsupported extension",
7478					})
7479
7480					// Test server ignore wrong codepoint from client.
7481					clientSends := ALPSUseCodepointNew
7482					if alpsCodePoint == ALPSUseCodepointNew {
7483						clientSends = ALPSUseCodepointOld
7484					}
7485
7486					testCases = append(testCases, testCase{
7487						protocol:           protocol,
7488						testType:           serverTest,
7489						name:               fmt.Sprintf("ALPS-IgnoreClientWrongCodepoint-Server-%s-%s", alpsCodePoint, suffix),
7490						skipQUICALPNConfig: true,
7491						config: Config{
7492							MaxVersion:          ver.version,
7493							NextProtos:          []string{"proto"},
7494							ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
7495							ALPSUseNewCodepoint: clientSends,
7496						},
7497						resumeConfig: &Config{
7498							MaxVersion:          ver.version,
7499							NextProtos:          []string{"proto"},
7500							ApplicationSettings: map[string][]byte{"proto": []byte("runner2")},
7501							ALPSUseNewCodepoint: clientSends,
7502						},
7503						resumeSession: true,
7504						flags: append([]string{
7505							"-select-alpn", "proto",
7506							"-on-initial-application-settings", "proto,shim1",
7507							"-on-resume-application-settings", "proto,shim2",
7508						}, alpsFlags...),
7509					})
7510
7511					// Test the server declines ALPS if it doesn't support it for the
7512					// specified protocol.
7513					testCases = append(testCases, testCase{
7514						protocol:           protocol,
7515						testType:           serverTest,
7516						name:               fmt.Sprintf("ALPS-UnsupportedProtocol-Server-%s-%s", alpsCodePoint, suffix),
7517						skipQUICALPNConfig: true,
7518						config: Config{
7519							MaxVersion:          ver.version,
7520							NextProtos:          []string{"proto1"},
7521							ApplicationSettings: map[string][]byte{"proto1": []byte("runner")},
7522							ALPSUseNewCodepoint: alpsCodePoint,
7523						},
7524						// The server supports ALPS with "proto2", but not "proto1".
7525						flags: append([]string{
7526							"-select-alpn", "proto1",
7527							"-application-settings", "proto2,shim",
7528						}, alpsFlags...),
7529					})
7530
7531					// Test the client rejects application settings from the server when
7532					// it always negotiate both codepoint.
7533					testCases = append(testCases, testCase{
7534						protocol:           protocol,
7535						testType:           clientTest,
7536						name:               fmt.Sprintf("ALPS-UnsupportedProtocol-Client-ServerBoth-%s-%s", alpsCodePoint, suffix),
7537						skipQUICALPNConfig: true,
7538						config: Config{
7539							MaxVersion:          ver.version,
7540							NextProtos:          []string{"proto1"},
7541							ApplicationSettings: map[string][]byte{"proto1": []byte("runner")},
7542							Bugs: ProtocolBugs{
7543								AlwaysNegotiateApplicationSettingsBoth: true,
7544							},
7545							ALPSUseNewCodepoint: alpsCodePoint,
7546						},
7547						flags: append([]string{
7548							"-advertise-alpn", "\x06proto1\x06proto2",
7549							"-application-settings", "proto1,shim",
7550							"-expect-alpn", "proto1",
7551						}, alpsFlags...),
7552						// The server sends ALPS with both application settings, which is invalid.
7553						shouldFail:         true,
7554						expectedError:      ":UNEXPECTED_EXTENSION:",
7555						expectedLocalError: "remote error: unsupported extension",
7556					})
7557
7558					expectations = connectionExpectations{
7559						peerApplicationSettingsOld: []byte("shim"),
7560					}
7561					if alpsCodePoint == ALPSUseCodepointNew {
7562						expectations = connectionExpectations{
7563							peerApplicationSettings: []byte("shim"),
7564						}
7565					}
7566
7567					// Test that the server rejects a missing application_settings extension.
7568					testCases = append(testCases, testCase{
7569						protocol:           protocol,
7570						testType:           serverTest,
7571						name:               fmt.Sprintf("ALPS-OmitClientApplicationSettings-%s-%s", alpsCodePoint, suffix),
7572						skipQUICALPNConfig: true,
7573						config: Config{
7574							MaxVersion:          ver.version,
7575							NextProtos:          []string{"proto"},
7576							ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
7577							Bugs: ProtocolBugs{
7578								OmitClientApplicationSettings: true,
7579							},
7580							ALPSUseNewCodepoint: alpsCodePoint,
7581						},
7582						flags: append([]string{
7583							"-select-alpn", "proto",
7584							"-application-settings", "proto,shim",
7585						}, alpsFlags...),
7586						// The runner is a client, so it only processes the shim's alert
7587						// after checking connection state.
7588						expectations:       expectations,
7589						shouldFail:         true,
7590						expectedError:      ":MISSING_EXTENSION:",
7591						expectedLocalError: "remote error: missing extension",
7592					})
7593
7594					// Test that the server rejects a missing EncryptedExtensions message.
7595					testCases = append(testCases, testCase{
7596						protocol:           protocol,
7597						testType:           serverTest,
7598						name:               fmt.Sprintf("ALPS-OmitClientEncryptedExtensions-%s-%s", alpsCodePoint, suffix),
7599						skipQUICALPNConfig: true,
7600						config: Config{
7601							MaxVersion:          ver.version,
7602							NextProtos:          []string{"proto"},
7603							ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
7604							Bugs: ProtocolBugs{
7605								OmitClientEncryptedExtensions: true,
7606							},
7607							ALPSUseNewCodepoint: alpsCodePoint,
7608						},
7609						flags: append([]string{
7610							"-select-alpn", "proto",
7611							"-application-settings", "proto,shim",
7612						}, alpsFlags...),
7613						// The runner is a client, so it only processes the shim's alert
7614						// after checking connection state.
7615						expectations:       expectations,
7616						shouldFail:         true,
7617						expectedError:      ":UNEXPECTED_MESSAGE:",
7618						expectedLocalError: "remote error: unexpected message",
7619					})
7620
7621					// Test that the server rejects an unexpected EncryptedExtensions message.
7622					testCases = append(testCases, testCase{
7623						protocol: protocol,
7624						testType: serverTest,
7625						name:     fmt.Sprintf("UnexpectedClientEncryptedExtensions-%s-%s", alpsCodePoint, suffix),
7626						config: Config{
7627							MaxVersion: ver.version,
7628							Bugs: ProtocolBugs{
7629								AlwaysSendClientEncryptedExtensions: true,
7630							},
7631							ALPSUseNewCodepoint: alpsCodePoint,
7632						},
7633						shouldFail:         true,
7634						expectedError:      ":UNEXPECTED_MESSAGE:",
7635						expectedLocalError: "remote error: unexpected message",
7636					})
7637
7638					// Test that the server rejects an unexpected extension in an
7639					// expected EncryptedExtensions message.
7640					testCases = append(testCases, testCase{
7641						protocol:           protocol,
7642						testType:           serverTest,
7643						name:               fmt.Sprintf("ExtraClientEncryptedExtension-%s-%s", alpsCodePoint, suffix),
7644						skipQUICALPNConfig: true,
7645						config: Config{
7646							MaxVersion:          ver.version,
7647							NextProtos:          []string{"proto"},
7648							ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
7649							Bugs: ProtocolBugs{
7650								SendExtraClientEncryptedExtension: true,
7651							},
7652							ALPSUseNewCodepoint: alpsCodePoint,
7653						},
7654						flags: append([]string{
7655							"-select-alpn", "proto",
7656							"-application-settings", "proto,shim",
7657						}, alpsFlags...),
7658						// The runner is a client, so it only processes the shim's alert
7659						// after checking connection state.
7660						expectations:       expectations,
7661						shouldFail:         true,
7662						expectedError:      ":UNEXPECTED_EXTENSION:",
7663						expectedLocalError: "remote error: unsupported extension",
7664					})
7665
7666					// Test that ALPS is carried over on 0-RTT.
7667					for _, empty := range []bool{false, true} {
7668						maybeEmpty := ""
7669						runnerSettings := "runner"
7670						shimSettings := "shim"
7671						if empty {
7672							maybeEmpty = "Empty-"
7673							runnerSettings = ""
7674							shimSettings = ""
7675						}
7676
7677						expectations = connectionExpectations{
7678							peerApplicationSettingsOld: []byte(shimSettings),
7679						}
7680						if alpsCodePoint == ALPSUseCodepointNew {
7681							expectations = connectionExpectations{
7682								peerApplicationSettings: []byte(shimSettings),
7683							}
7684						}
7685						testCases = append(testCases, testCase{
7686							protocol:           protocol,
7687							testType:           clientTest,
7688							name:               fmt.Sprintf("ALPS-EarlyData-Client-%s-%s-%s", alpsCodePoint, maybeEmpty, suffix),
7689							skipQUICALPNConfig: true,
7690							config: Config{
7691								MaxVersion:          ver.version,
7692								NextProtos:          []string{"proto"},
7693								ApplicationSettings: map[string][]byte{"proto": []byte(runnerSettings)},
7694								ALPSUseNewCodepoint: alpsCodePoint,
7695							},
7696							resumeSession: true,
7697							earlyData:     true,
7698							flags: append([]string{
7699								"-advertise-alpn", "\x05proto",
7700								"-expect-alpn", "proto",
7701								"-application-settings", "proto," + shimSettings,
7702								"-expect-peer-application-settings", runnerSettings,
7703							}, alpsFlags...),
7704							expectations: expectations,
7705						})
7706						testCases = append(testCases, testCase{
7707							protocol:           protocol,
7708							testType:           serverTest,
7709							name:               fmt.Sprintf("ALPS-EarlyData-Server-%s-%s-%s", alpsCodePoint, maybeEmpty, suffix),
7710							skipQUICALPNConfig: true,
7711							config: Config{
7712								MaxVersion:          ver.version,
7713								NextProtos:          []string{"proto"},
7714								ApplicationSettings: map[string][]byte{"proto": []byte(runnerSettings)},
7715								ALPSUseNewCodepoint: alpsCodePoint,
7716							},
7717							resumeSession: true,
7718							earlyData:     true,
7719							flags: append([]string{
7720								"-select-alpn", "proto",
7721								"-application-settings", "proto," + shimSettings,
7722								"-expect-peer-application-settings", runnerSettings,
7723							}, alpsFlags...),
7724							expectations: expectations,
7725						})
7726
7727						// Sending application settings in 0-RTT handshakes is forbidden.
7728						testCases = append(testCases, testCase{
7729							protocol:           protocol,
7730							testType:           clientTest,
7731							name:               fmt.Sprintf("ALPS-EarlyData-SendApplicationSettingsWithEarlyData-Client-%s-%s-%s", alpsCodePoint, maybeEmpty, suffix),
7732							skipQUICALPNConfig: true,
7733							config: Config{
7734								MaxVersion:          ver.version,
7735								NextProtos:          []string{"proto"},
7736								ApplicationSettings: map[string][]byte{"proto": []byte(runnerSettings)},
7737								Bugs: ProtocolBugs{
7738									SendApplicationSettingsWithEarlyData: true,
7739								},
7740								ALPSUseNewCodepoint: alpsCodePoint,
7741							},
7742							resumeSession: true,
7743							earlyData:     true,
7744							flags: append([]string{
7745								"-advertise-alpn", "\x05proto",
7746								"-expect-alpn", "proto",
7747								"-application-settings", "proto," + shimSettings,
7748								"-expect-peer-application-settings", runnerSettings,
7749							}, alpsFlags...),
7750							expectations:       expectations,
7751							shouldFail:         true,
7752							expectedError:      ":UNEXPECTED_EXTENSION_ON_EARLY_DATA:",
7753							expectedLocalError: "remote error: illegal parameter",
7754						})
7755						testCases = append(testCases, testCase{
7756							protocol:           protocol,
7757							testType:           serverTest,
7758							name:               fmt.Sprintf("ALPS-EarlyData-SendApplicationSettingsWithEarlyData-Server-%s-%s-%s", alpsCodePoint, maybeEmpty, suffix),
7759							skipQUICALPNConfig: true,
7760							config: Config{
7761								MaxVersion:          ver.version,
7762								NextProtos:          []string{"proto"},
7763								ApplicationSettings: map[string][]byte{"proto": []byte(runnerSettings)},
7764								Bugs: ProtocolBugs{
7765									SendApplicationSettingsWithEarlyData: true,
7766								},
7767								ALPSUseNewCodepoint: alpsCodePoint,
7768							},
7769							resumeSession: true,
7770							earlyData:     true,
7771							flags: append([]string{
7772								"-select-alpn", "proto",
7773								"-application-settings", "proto," + shimSettings,
7774								"-expect-peer-application-settings", runnerSettings,
7775							}, alpsFlags...),
7776							expectations:       expectations,
7777							shouldFail:         true,
7778							expectedError:      ":UNEXPECTED_MESSAGE:",
7779							expectedLocalError: "remote error: unexpected message",
7780						})
7781					}
7782
7783					// Test that the client and server each decline early data if local
7784					// ALPS preferences has changed for the current connection.
7785					alpsMismatchTests := []struct {
7786						name                            string
7787						initialSettings, resumeSettings []byte
7788					}{
7789						{"DifferentValues", []byte("settings1"), []byte("settings2")},
7790						{"OnOff", []byte("settings"), nil},
7791						{"OffOn", nil, []byte("settings")},
7792						// The empty settings value should not be mistaken for ALPS not
7793						// being negotiated.
7794						{"OnEmpty", []byte("settings"), []byte{}},
7795						{"EmptyOn", []byte{}, []byte("settings")},
7796						{"EmptyOff", []byte{}, nil},
7797						{"OffEmpty", nil, []byte{}},
7798					}
7799					for _, test := range alpsMismatchTests {
7800						flags := []string{"-on-resume-expect-early-data-reason", "alps_mismatch"}
7801						flags = append(flags, alpsFlags...)
7802						if test.initialSettings != nil {
7803							flags = append(flags, "-on-initial-application-settings", "proto,"+string(test.initialSettings))
7804							flags = append(flags, "-on-initial-expect-peer-application-settings", "runner")
7805						}
7806						if test.resumeSettings != nil {
7807							flags = append(flags, "-on-resume-application-settings", "proto,"+string(test.resumeSettings))
7808							flags = append(flags, "-on-resume-expect-peer-application-settings", "runner")
7809						}
7810
7811						expectations = connectionExpectations{
7812							peerApplicationSettingsOld: test.initialSettings,
7813						}
7814						resumeExpectations = &connectionExpectations{
7815							peerApplicationSettingsOld: test.resumeSettings,
7816						}
7817						if alpsCodePoint == ALPSUseCodepointNew {
7818							expectations = connectionExpectations{
7819								peerApplicationSettings: test.initialSettings,
7820							}
7821							resumeExpectations = &connectionExpectations{
7822								peerApplicationSettings: test.resumeSettings,
7823							}
7824						}
7825						// The client should not offer early data if the session is
7826						// inconsistent with the new configuration. Note that if
7827						// the session did not negotiate ALPS (test.initialSettings
7828						// is nil), the client always offers early data.
7829						if test.initialSettings != nil {
7830							testCases = append(testCases, testCase{
7831								protocol:           protocol,
7832								testType:           clientTest,
7833								name:               fmt.Sprintf("ALPS-EarlyData-Mismatch-%s-Client-%s-%s", test.name, alpsCodePoint, suffix),
7834								skipQUICALPNConfig: true,
7835								config: Config{
7836									MaxVersion:          ver.version,
7837									MaxEarlyDataSize:    16384,
7838									NextProtos:          []string{"proto"},
7839									ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
7840									ALPSUseNewCodepoint: alpsCodePoint,
7841								},
7842								resumeSession: true,
7843								flags: append([]string{
7844									"-enable-early-data",
7845									"-expect-ticket-supports-early-data",
7846									"-expect-no-offer-early-data",
7847									"-advertise-alpn", "\x05proto",
7848									"-expect-alpn", "proto",
7849								}, flags...),
7850								expectations:       expectations,
7851								resumeExpectations: resumeExpectations,
7852							})
7853						}
7854
7855						// The server should reject early data if the session is
7856						// inconsistent with the new selection.
7857						testCases = append(testCases, testCase{
7858							protocol:           protocol,
7859							testType:           serverTest,
7860							name:               fmt.Sprintf("ALPS-EarlyData-Mismatch-%s-Server-%s-%s", test.name, alpsCodePoint, suffix),
7861							skipQUICALPNConfig: true,
7862							config: Config{
7863								MaxVersion:          ver.version,
7864								NextProtos:          []string{"proto"},
7865								ApplicationSettings: map[string][]byte{"proto": []byte("runner")},
7866								ALPSUseNewCodepoint: alpsCodePoint,
7867							},
7868							resumeSession:           true,
7869							earlyData:               true,
7870							expectEarlyDataRejected: true,
7871							flags: append([]string{
7872								"-select-alpn", "proto",
7873							}, flags...),
7874							expectations:       expectations,
7875							resumeExpectations: resumeExpectations,
7876						})
7877					}
7878
7879					// Test that 0-RTT continues working when the shim configures
7880					// ALPS but the peer does not.
7881					testCases = append(testCases, testCase{
7882						protocol:           protocol,
7883						testType:           clientTest,
7884						name:               fmt.Sprintf("ALPS-EarlyData-Client-ServerDecline-%s-%s", alpsCodePoint, suffix),
7885						skipQUICALPNConfig: true,
7886						config: Config{
7887							MaxVersion:          ver.version,
7888							NextProtos:          []string{"proto"},
7889							ALPSUseNewCodepoint: alpsCodePoint,
7890						},
7891						resumeSession: true,
7892						earlyData:     true,
7893						flags: append([]string{
7894							"-advertise-alpn", "\x05proto",
7895							"-expect-alpn", "proto",
7896							"-application-settings", "proto,shim",
7897						}, alpsFlags...),
7898					})
7899					testCases = append(testCases, testCase{
7900						protocol:           protocol,
7901						testType:           serverTest,
7902						name:               fmt.Sprintf("ALPS-EarlyData-Server-ClientNoOffe-%s-%s", alpsCodePoint, suffix),
7903						skipQUICALPNConfig: true,
7904						config: Config{
7905							MaxVersion:          ver.version,
7906							NextProtos:          []string{"proto"},
7907							ALPSUseNewCodepoint: alpsCodePoint,
7908						},
7909						resumeSession: true,
7910						earlyData:     true,
7911						flags: append([]string{
7912							"-select-alpn", "proto",
7913							"-application-settings", "proto,shim",
7914						}, alpsFlags...),
7915					})
7916				}
7917			} else {
7918				// Test the client rejects the ALPS extension if the server
7919				// negotiated TLS 1.2 or below.
7920				for _, alpsCodePoint := range []ALPSUseCodepoint{ALPSUseCodepointNew, ALPSUseCodepointOld} {
7921					flags := []string{
7922						"-advertise-alpn", "\x03foo",
7923						"-expect-alpn", "foo",
7924						"-application-settings", "foo,shim",
7925					}
7926					bugs := ProtocolBugs{
7927						AlwaysNegotiateApplicationSettingsOld: true,
7928					}
7929					if alpsCodePoint == ALPSUseCodepointNew {
7930						flags = append(flags, "-alps-use-new-codepoint")
7931						bugs = ProtocolBugs{
7932							AlwaysNegotiateApplicationSettingsNew: true,
7933						}
7934					}
7935					testCases = append(testCases, testCase{
7936						protocol: protocol,
7937						testType: clientTest,
7938						name:     fmt.Sprintf("ALPS-Reject-Client-%s-%s", alpsCodePoint, suffix),
7939						config: Config{
7940							MaxVersion:          ver.version,
7941							NextProtos:          []string{"foo"},
7942							ApplicationSettings: map[string][]byte{"foo": []byte("runner")},
7943							Bugs:                bugs,
7944							ALPSUseNewCodepoint: alpsCodePoint,
7945						},
7946						flags:              flags,
7947						shouldFail:         true,
7948						expectedError:      ":UNEXPECTED_EXTENSION:",
7949						expectedLocalError: "remote error: unsupported extension",
7950					})
7951
7952					flags = []string{
7953						"-on-resume-advertise-alpn", "\x03foo",
7954						"-on-resume-expect-alpn", "foo",
7955						"-on-resume-application-settings", "foo,shim",
7956					}
7957					bugs = ProtocolBugs{
7958						AlwaysNegotiateApplicationSettingsOld: true,
7959					}
7960					if alpsCodePoint == ALPSUseCodepointNew {
7961						flags = append(flags, "-alps-use-new-codepoint")
7962						bugs = ProtocolBugs{
7963							AlwaysNegotiateApplicationSettingsNew: true,
7964						}
7965					}
7966					testCases = append(testCases, testCase{
7967						protocol: protocol,
7968						testType: clientTest,
7969						name:     fmt.Sprintf("ALPS-Reject-Client-Resume-%s-%s", alpsCodePoint, suffix),
7970						config: Config{
7971							MaxVersion: ver.version,
7972						},
7973						resumeConfig: &Config{
7974							MaxVersion:          ver.version,
7975							NextProtos:          []string{"foo"},
7976							ApplicationSettings: map[string][]byte{"foo": []byte("runner")},
7977							Bugs:                bugs,
7978							ALPSUseNewCodepoint: alpsCodePoint,
7979						},
7980						resumeSession:      true,
7981						flags:              flags,
7982						shouldFail:         true,
7983						expectedError:      ":UNEXPECTED_EXTENSION:",
7984						expectedLocalError: "remote error: unsupported extension",
7985					})
7986
7987					// Test the server declines ALPS if it negotiates TLS 1.2 or below.
7988					flags = []string{
7989						"-select-alpn", "foo",
7990						"-application-settings", "foo,shim",
7991					}
7992					if alpsCodePoint == ALPSUseCodepointNew {
7993						flags = append(flags, "-alps-use-new-codepoint")
7994					}
7995					testCases = append(testCases, testCase{
7996						protocol: protocol,
7997						testType: serverTest,
7998						name:     fmt.Sprintf("ALPS-Decline-Server-%s-%s", alpsCodePoint, suffix),
7999						config: Config{
8000							MaxVersion:          ver.version,
8001							NextProtos:          []string{"foo"},
8002							ApplicationSettings: map[string][]byte{"foo": []byte("runner")},
8003							ALPSUseNewCodepoint: alpsCodePoint,
8004						},
8005						// Test both TLS 1.2 full and resumption handshakes.
8006						resumeSession: true,
8007						flags:         flags,
8008						// If not specified, runner and shim both implicitly expect ALPS
8009						// is not negotiated.
8010					})
8011				}
8012			}
8013
8014			// Test QUIC transport params
8015			if protocol == quic {
8016				// Client sends params
8017				for _, clientConfig := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy} {
8018					for _, serverSends := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy, QUICUseCodepointBoth, QUICUseCodepointNeither} {
8019						useCodepointFlag := "0"
8020						if clientConfig == QUICUseCodepointLegacy {
8021							useCodepointFlag = "1"
8022						}
8023						flags := []string{
8024							"-quic-transport-params",
8025							base64FlagValue([]byte{1, 2}),
8026							"-quic-use-legacy-codepoint", useCodepointFlag,
8027						}
8028						expectations := connectionExpectations{
8029							quicTransportParams: []byte{1, 2},
8030						}
8031						shouldFail := false
8032						expectedError := ""
8033						expectedLocalError := ""
8034						if clientConfig == QUICUseCodepointLegacy {
8035							expectations = connectionExpectations{
8036								quicTransportParamsLegacy: []byte{1, 2},
8037							}
8038						}
8039						if serverSends != clientConfig {
8040							expectations = connectionExpectations{}
8041							shouldFail = true
8042							if serverSends == QUICUseCodepointNeither {
8043								expectedError = ":MISSING_EXTENSION:"
8044							} else {
8045								expectedLocalError = "remote error: unsupported extension"
8046							}
8047						} else {
8048							flags = append(flags,
8049								"-expect-quic-transport-params",
8050								base64FlagValue([]byte{3, 4}))
8051						}
8052						testCases = append(testCases, testCase{
8053							testType: clientTest,
8054							protocol: protocol,
8055							name:     fmt.Sprintf("QUICTransportParams-Client-Client%s-Server%s-%s", clientConfig, serverSends, suffix),
8056							config: Config{
8057								MinVersion:                            ver.version,
8058								MaxVersion:                            ver.version,
8059								QUICTransportParams:                   []byte{3, 4},
8060								QUICTransportParamsUseLegacyCodepoint: serverSends,
8061							},
8062							flags:                     flags,
8063							expectations:              expectations,
8064							shouldFail:                shouldFail,
8065							expectedError:             expectedError,
8066							expectedLocalError:        expectedLocalError,
8067							skipTransportParamsConfig: true,
8068						})
8069					}
8070				}
8071				// Server sends params
8072				for _, clientSends := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy, QUICUseCodepointBoth, QUICUseCodepointNeither} {
8073					for _, serverConfig := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy} {
8074						expectations := connectionExpectations{
8075							quicTransportParams: []byte{3, 4},
8076						}
8077						shouldFail := false
8078						expectedError := ""
8079						useCodepointFlag := "0"
8080						if serverConfig == QUICUseCodepointLegacy {
8081							useCodepointFlag = "1"
8082							expectations = connectionExpectations{
8083								quicTransportParamsLegacy: []byte{3, 4},
8084							}
8085						}
8086						flags := []string{
8087							"-quic-transport-params",
8088							base64FlagValue([]byte{3, 4}),
8089							"-quic-use-legacy-codepoint", useCodepointFlag,
8090						}
8091						if clientSends != QUICUseCodepointBoth && clientSends != serverConfig {
8092							expectations = connectionExpectations{}
8093							shouldFail = true
8094							expectedError = ":MISSING_EXTENSION:"
8095						} else {
8096							flags = append(flags,
8097								"-expect-quic-transport-params",
8098								base64FlagValue([]byte{1, 2}),
8099							)
8100						}
8101						testCases = append(testCases, testCase{
8102							testType: serverTest,
8103							protocol: protocol,
8104							name:     fmt.Sprintf("QUICTransportParams-Server-Client%s-Server%s-%s", clientSends, serverConfig, suffix),
8105							config: Config{
8106								MinVersion:                            ver.version,
8107								MaxVersion:                            ver.version,
8108								QUICTransportParams:                   []byte{1, 2},
8109								QUICTransportParamsUseLegacyCodepoint: clientSends,
8110							},
8111							flags:                     flags,
8112							expectations:              expectations,
8113							shouldFail:                shouldFail,
8114							expectedError:             expectedError,
8115							skipTransportParamsConfig: true,
8116						})
8117					}
8118				}
8119			} else {
8120				// Ensure non-QUIC client doesn't send QUIC transport parameters.
8121				for _, clientConfig := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy} {
8122					useCodepointFlag := "0"
8123					if clientConfig == QUICUseCodepointLegacy {
8124						useCodepointFlag = "1"
8125					}
8126					testCases = append(testCases, testCase{
8127						protocol: protocol,
8128						testType: clientTest,
8129						name:     fmt.Sprintf("QUICTransportParams-Client-NotSentInNonQUIC-%s-%s", clientConfig, suffix),
8130						config: Config{
8131							MinVersion:                            ver.version,
8132							MaxVersion:                            ver.version,
8133							QUICTransportParamsUseLegacyCodepoint: clientConfig,
8134						},
8135						flags: []string{
8136							"-max-version",
8137							strconv.Itoa(int(ver.versionWire)),
8138							"-quic-transport-params",
8139							base64FlagValue([]byte{3, 4}),
8140							"-quic-use-legacy-codepoint", useCodepointFlag,
8141						},
8142						shouldFail:                true,
8143						expectedError:             ":QUIC_TRANSPORT_PARAMETERS_MISCONFIGURED:",
8144						skipTransportParamsConfig: true,
8145					})
8146				}
8147				// Ensure non-QUIC server rejects codepoint 57 but ignores legacy 0xffa5.
8148				for _, clientSends := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy, QUICUseCodepointBoth, QUICUseCodepointNeither} {
8149					for _, serverConfig := range []QUICUseCodepoint{QUICUseCodepointStandard, QUICUseCodepointLegacy} {
8150						shouldFail := false
8151						expectedLocalError := ""
8152						useCodepointFlag := "0"
8153						if serverConfig == QUICUseCodepointLegacy {
8154							useCodepointFlag = "1"
8155						}
8156						if clientSends == QUICUseCodepointStandard || clientSends == QUICUseCodepointBoth {
8157							shouldFail = true
8158							expectedLocalError = "remote error: unsupported extension"
8159						}
8160						testCases = append(testCases, testCase{
8161							protocol: protocol,
8162							testType: serverTest,
8163							name:     fmt.Sprintf("QUICTransportParams-NonQUICServer-Client%s-Server%s-%s", clientSends, serverConfig, suffix),
8164							config: Config{
8165								MinVersion:                            ver.version,
8166								MaxVersion:                            ver.version,
8167								QUICTransportParams:                   []byte{1, 2},
8168								QUICTransportParamsUseLegacyCodepoint: clientSends,
8169							},
8170							flags: []string{
8171								"-quic-use-legacy-codepoint", useCodepointFlag,
8172							},
8173							shouldFail:                shouldFail,
8174							expectedLocalError:        expectedLocalError,
8175							skipTransportParamsConfig: true,
8176						})
8177					}
8178				}
8179
8180			}
8181
8182			// Test ticket behavior.
8183
8184			// Resume with a corrupt ticket.
8185			testCases = append(testCases, testCase{
8186				protocol: protocol,
8187				testType: serverTest,
8188				name:     "CorruptTicket-" + suffix,
8189				config: Config{
8190					MaxVersion: ver.version,
8191					Bugs: ProtocolBugs{
8192						FilterTicket: func(in []byte) ([]byte, error) {
8193							in[len(in)-1] ^= 1
8194							return in, nil
8195						},
8196					},
8197				},
8198				resumeSession:        true,
8199				expectResumeRejected: true,
8200			})
8201			// Test the ticket callback, with and without renewal.
8202			testCases = append(testCases, testCase{
8203				protocol: protocol,
8204				testType: serverTest,
8205				name:     "TicketCallback-" + suffix,
8206				config: Config{
8207					MaxVersion: ver.version,
8208				},
8209				resumeSession: true,
8210				flags:         []string{"-use-ticket-callback"},
8211			})
8212			testCases = append(testCases, testCase{
8213				protocol: protocol,
8214				testType: serverTest,
8215				name:     "TicketCallback-Renew-" + suffix,
8216				config: Config{
8217					MaxVersion: ver.version,
8218					Bugs: ProtocolBugs{
8219						ExpectNewTicket: true,
8220					},
8221				},
8222				flags:         []string{"-use-ticket-callback", "-renew-ticket"},
8223				resumeSession: true,
8224			})
8225
8226			// Test that the ticket callback is only called once when everything before
8227			// it in the ClientHello is asynchronous. This corrupts the ticket so
8228			// certificate selection callbacks run.
8229			testCases = append(testCases, testCase{
8230				protocol: protocol,
8231				testType: serverTest,
8232				name:     "TicketCallback-SingleCall-" + suffix,
8233				config: Config{
8234					MaxVersion: ver.version,
8235					Bugs: ProtocolBugs{
8236						FilterTicket: func(in []byte) ([]byte, error) {
8237							in[len(in)-1] ^= 1
8238							return in, nil
8239						},
8240					},
8241				},
8242				resumeSession:        true,
8243				expectResumeRejected: true,
8244				flags: []string{
8245					"-use-ticket-callback",
8246					"-async",
8247				},
8248			})
8249
8250			// Resume with various lengths of ticket session id.
8251			if ver.version < VersionTLS13 {
8252				testCases = append(testCases, testCase{
8253					protocol: protocol,
8254					testType: serverTest,
8255					name:     "TicketSessionIDLength-0-" + suffix,
8256					config: Config{
8257						MaxVersion: ver.version,
8258						Bugs: ProtocolBugs{
8259							EmptyTicketSessionID: true,
8260						},
8261					},
8262					resumeSession: true,
8263				})
8264				testCases = append(testCases, testCase{
8265					protocol: protocol,
8266					testType: serverTest,
8267					name:     "TicketSessionIDLength-16-" + suffix,
8268					config: Config{
8269						MaxVersion: ver.version,
8270						Bugs: ProtocolBugs{
8271							TicketSessionIDLength: 16,
8272						},
8273					},
8274					resumeSession: true,
8275				})
8276				testCases = append(testCases, testCase{
8277					protocol: protocol,
8278					testType: serverTest,
8279					name:     "TicketSessionIDLength-32-" + suffix,
8280					config: Config{
8281						MaxVersion: ver.version,
8282						Bugs: ProtocolBugs{
8283							TicketSessionIDLength: 32,
8284						},
8285					},
8286					resumeSession: true,
8287				})
8288				testCases = append(testCases, testCase{
8289					protocol: protocol,
8290					testType: serverTest,
8291					name:     "TicketSessionIDLength-33-" + suffix,
8292					config: Config{
8293						MaxVersion: ver.version,
8294						Bugs: ProtocolBugs{
8295							TicketSessionIDLength: 33,
8296						},
8297					},
8298					resumeSession: true,
8299					shouldFail:    true,
8300					// The maximum session ID length is 32.
8301					expectedError: ":DECODE_ERROR:",
8302				})
8303			}
8304
8305			// Basic DTLS-SRTP tests. Include fake profiles to ensure they
8306			// are ignored.
8307			if protocol == dtls {
8308				testCases = append(testCases, testCase{
8309					protocol: protocol,
8310					name:     "SRTP-Client-" + suffix,
8311					config: Config{
8312						MaxVersion:             ver.version,
8313						SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
8314					},
8315					flags: []string{
8316						"-srtp-profiles",
8317						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
8318					},
8319					expectations: connectionExpectations{
8320						srtpProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
8321					},
8322				})
8323				testCases = append(testCases, testCase{
8324					protocol: protocol,
8325					testType: serverTest,
8326					name:     "SRTP-Server-" + suffix,
8327					config: Config{
8328						MaxVersion:             ver.version,
8329						SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
8330					},
8331					flags: []string{
8332						"-srtp-profiles",
8333						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
8334					},
8335					expectations: connectionExpectations{
8336						srtpProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
8337					},
8338				})
8339				// Test that the MKI is ignored.
8340				testCases = append(testCases, testCase{
8341					protocol: protocol,
8342					testType: serverTest,
8343					name:     "SRTP-Server-IgnoreMKI-" + suffix,
8344					config: Config{
8345						MaxVersion:             ver.version,
8346						SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
8347						Bugs: ProtocolBugs{
8348							SRTPMasterKeyIdentifier: "bogus",
8349						},
8350					},
8351					flags: []string{
8352						"-srtp-profiles",
8353						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
8354					},
8355					expectations: connectionExpectations{
8356						srtpProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
8357					},
8358				})
8359				// Test that SRTP isn't negotiated on the server if there were
8360				// no matching profiles.
8361				testCases = append(testCases, testCase{
8362					protocol: protocol,
8363					testType: serverTest,
8364					name:     "SRTP-Server-NoMatch-" + suffix,
8365					config: Config{
8366						MaxVersion:             ver.version,
8367						SRTPProtectionProfiles: []uint16{100, 101, 102},
8368					},
8369					flags: []string{
8370						"-srtp-profiles",
8371						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
8372					},
8373					expectations: connectionExpectations{
8374						srtpProtectionProfile: 0,
8375					},
8376				})
8377				// Test that the server returning an invalid SRTP profile is
8378				// flagged as an error by the client.
8379				testCases = append(testCases, testCase{
8380					protocol: protocol,
8381					name:     "SRTP-Client-NoMatch-" + suffix,
8382					config: Config{
8383						MaxVersion: ver.version,
8384						Bugs: ProtocolBugs{
8385							SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
8386						},
8387					},
8388					flags: []string{
8389						"-srtp-profiles",
8390						"SRTP_AES128_CM_SHA1_80",
8391					},
8392					shouldFail:    true,
8393					expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
8394				})
8395			} else {
8396				// DTLS-SRTP is not defined for other protocols. Configuring it
8397				// on the client and server should ignore the extension.
8398				testCases = append(testCases, testCase{
8399					protocol: protocol,
8400					name:     "SRTP-Client-Ignore-" + suffix,
8401					config: Config{
8402						MaxVersion:             ver.version,
8403						SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
8404					},
8405					flags: []string{
8406						"-srtp-profiles",
8407						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
8408					},
8409					expectations: connectionExpectations{
8410						srtpProtectionProfile: 0,
8411					},
8412				})
8413				testCases = append(testCases, testCase{
8414					protocol: protocol,
8415					testType: serverTest,
8416					name:     "SRTP-Server-Ignore-" + suffix,
8417					config: Config{
8418						MaxVersion:             ver.version,
8419						SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
8420					},
8421					flags: []string{
8422						"-srtp-profiles",
8423						"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
8424					},
8425					expectations: connectionExpectations{
8426						srtpProtectionProfile: 0,
8427					},
8428				})
8429			}
8430
8431			// Test SCT list.
8432			testCases = append(testCases, testCase{
8433				protocol: protocol,
8434				name:     "SignedCertificateTimestampList-Client-" + suffix,
8435				testType: clientTest,
8436				config: Config{
8437					MaxVersion: ver.version,
8438					Credential: rsaCertificate.WithSCTList(testSCTList),
8439				},
8440				flags: []string{
8441					"-enable-signed-cert-timestamps",
8442					"-expect-signed-cert-timestamps",
8443					base64FlagValue(testSCTList),
8444				},
8445				resumeSession: true,
8446			})
8447
8448			var differentSCTList []byte
8449			differentSCTList = append(differentSCTList, testSCTList...)
8450			differentSCTList[len(differentSCTList)-1] ^= 1
8451
8452			// The SCT extension did not specify that it must only be sent on resumption as it
8453			// should have, so test that we tolerate but ignore it.
8454			testCases = append(testCases, testCase{
8455				protocol: protocol,
8456				name:     "SendSCTListOnResume-" + suffix,
8457				config: Config{
8458					MaxVersion: ver.version,
8459					Credential: rsaCertificate.WithSCTList(testSCTList),
8460					Bugs: ProtocolBugs{
8461						SendSCTListOnResume: differentSCTList,
8462					},
8463				},
8464				flags: []string{
8465					"-enable-signed-cert-timestamps",
8466					"-expect-signed-cert-timestamps",
8467					base64FlagValue(testSCTList),
8468				},
8469				resumeSession: true,
8470			})
8471
8472			testCases = append(testCases, testCase{
8473				protocol: protocol,
8474				name:     "SignedCertificateTimestampList-Server-" + suffix,
8475				testType: serverTest,
8476				config: Config{
8477					MaxVersion: ver.version,
8478				},
8479				shimCertificate: rsaCertificate.WithSCTList(testSCTList),
8480				expectations: connectionExpectations{
8481					peerCertificate: rsaCertificate.WithSCTList(testSCTList),
8482				},
8483				resumeSession: true,
8484			})
8485
8486			// Test empty SCT list.
8487			testCases = append(testCases, testCase{
8488				protocol: protocol,
8489				name:     "SignedCertificateTimestampListEmpty-Client-" + suffix,
8490				testType: clientTest,
8491				config: Config{
8492					MaxVersion: ver.version,
8493					Credential: rsaCertificate.WithSCTList([]byte{0, 0}),
8494				},
8495				flags: []string{
8496					"-enable-signed-cert-timestamps",
8497				},
8498				shouldFail:    true,
8499				expectedError: ":ERROR_PARSING_EXTENSION:",
8500			})
8501
8502			// Test empty SCT in non-empty list.
8503			testCases = append(testCases, testCase{
8504				protocol: protocol,
8505				name:     "SignedCertificateTimestampListEmptySCT-Client-" + suffix,
8506				testType: clientTest,
8507				config: Config{
8508					MaxVersion: ver.version,
8509					Credential: rsaCertificate.WithSCTList([]byte{0, 6, 0, 2, 1, 2, 0, 0}),
8510				},
8511				flags: []string{
8512					"-enable-signed-cert-timestamps",
8513				},
8514				shouldFail:    true,
8515				expectedError: ":ERROR_PARSING_EXTENSION:",
8516			})
8517
8518			// Test that certificate-related extensions are not sent unsolicited.
8519			testCases = append(testCases, testCase{
8520				protocol: protocol,
8521				testType: serverTest,
8522				name:     "UnsolicitedCertificateExtensions-" + suffix,
8523				config: Config{
8524					MaxVersion: ver.version,
8525					Bugs: ProtocolBugs{
8526						NoOCSPStapling:                true,
8527						NoSignedCertificateTimestamps: true,
8528					},
8529				},
8530				shimCertificate: rsaCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
8531			})
8532
8533			// Extension permutation should interact correctly with other extensions,
8534			// HelloVerifyRequest, HelloRetryRequest, and ECH. SSLTest.PermuteExtensions
8535			// in ssl_test.cc tests that the extensions are actually permuted. This
8536			// tests the handshake still works.
8537			//
8538			// This test also tests that all our extensions interact with each other.
8539			for _, ech := range []bool{false, true} {
8540				if ech && ver.version < VersionTLS13 {
8541					continue
8542				}
8543
8544				test := testCase{
8545					protocol:           protocol,
8546					name:               "AllExtensions-Client-Permute",
8547					skipQUICALPNConfig: true,
8548					config: Config{
8549						MinVersion:          ver.version,
8550						MaxVersion:          ver.version,
8551						Credential:          rsaCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
8552						NextProtos:          []string{"proto"},
8553						ApplicationSettings: map[string][]byte{"proto": []byte("runner1")},
8554						Bugs: ProtocolBugs{
8555							SendServerNameAck: true,
8556							ExpectServerName:  "example.com",
8557							ExpectGREASE:      true,
8558						},
8559					},
8560					resumeSession: true,
8561					flags: []string{
8562						"-permute-extensions",
8563						"-enable-grease",
8564						"-enable-ocsp-stapling",
8565						"-enable-signed-cert-timestamps",
8566						"-advertise-alpn", "\x05proto",
8567						"-expect-alpn", "proto",
8568						"-host-name", "example.com",
8569					},
8570				}
8571
8572				if ech {
8573					test.name += "-ECH"
8574					echConfig := generateServerECHConfig(&ECHConfig{ConfigID: 42})
8575					test.config.ServerECHConfigs = []ServerECHConfig{echConfig}
8576					test.flags = append(test.flags,
8577						"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
8578						"-expect-ech-accept",
8579					)
8580					test.expectations.echAccepted = true
8581				}
8582
8583				if ver.version >= VersionTLS13 {
8584					// Trigger a HelloRetryRequest to test both ClientHellos. Note
8585					// our DTLS tests always enable HelloVerifyRequest.
8586					test.name += "-HelloRetryRequest"
8587
8588					// ALPS is only available on TLS 1.3.
8589					test.config.ApplicationSettings = map[string][]byte{"proto": []byte("runner")}
8590					test.flags = append(test.flags,
8591						"-application-settings", "proto,shim",
8592						"-alps-use-new-codepoint",
8593						"-expect-peer-application-settings", "runner")
8594					test.expectations.peerApplicationSettings = []byte("shim")
8595				}
8596
8597				if protocol == dtls {
8598					test.config.SRTPProtectionProfiles = []uint16{SRTP_AES128_CM_HMAC_SHA1_80}
8599					test.flags = append(test.flags, "-srtp-profiles", "SRTP_AES128_CM_SHA1_80")
8600					test.expectations.srtpProtectionProfile = SRTP_AES128_CM_HMAC_SHA1_80
8601				}
8602
8603				test.name += "-" + suffix
8604				testCases = append(testCases, test)
8605			}
8606		}
8607	}
8608
8609	testCases = append(testCases, testCase{
8610		testType: clientTest,
8611		name:     "ClientHelloPadding",
8612		config: Config{
8613			Bugs: ProtocolBugs{
8614				RequireClientHelloSize: 512,
8615			},
8616		},
8617		// This hostname just needs to be long enough to push the
8618		// ClientHello into F5's danger zone between 256 and 511 bytes
8619		// long.
8620		flags: []string{"-host-name", "01234567890123456789012345678901234567890123456789012345678901234567890123456789.com"},
8621	})
8622
8623	// Test that illegal extensions in TLS 1.3 are rejected by the client if
8624	// in ServerHello.
8625	testCases = append(testCases, testCase{
8626		name: "NPN-Forbidden-TLS13",
8627		config: Config{
8628			MaxVersion: VersionTLS13,
8629			NextProtos: []string{"foo"},
8630			Bugs: ProtocolBugs{
8631				NegotiateNPNAtAllVersions: true,
8632			},
8633		},
8634		flags:         []string{"-select-next-proto", "foo"},
8635		shouldFail:    true,
8636		expectedError: ":ERROR_PARSING_EXTENSION:",
8637	})
8638	testCases = append(testCases, testCase{
8639		name: "EMS-Forbidden-TLS13",
8640		config: Config{
8641			MaxVersion: VersionTLS13,
8642			Bugs: ProtocolBugs{
8643				NegotiateEMSAtAllVersions: true,
8644			},
8645		},
8646		shouldFail:    true,
8647		expectedError: ":ERROR_PARSING_EXTENSION:",
8648	})
8649	testCases = append(testCases, testCase{
8650		name: "RenegotiationInfo-Forbidden-TLS13",
8651		config: Config{
8652			MaxVersion: VersionTLS13,
8653			Bugs: ProtocolBugs{
8654				NegotiateRenegotiationInfoAtAllVersions: true,
8655			},
8656		},
8657		shouldFail:    true,
8658		expectedError: ":ERROR_PARSING_EXTENSION:",
8659	})
8660	testCases = append(testCases, testCase{
8661		name: "Ticket-Forbidden-TLS13",
8662		config: Config{
8663			MaxVersion: VersionTLS12,
8664		},
8665		resumeConfig: &Config{
8666			MaxVersion: VersionTLS13,
8667			Bugs: ProtocolBugs{
8668				AdvertiseTicketExtension: true,
8669			},
8670		},
8671		resumeSession: true,
8672		shouldFail:    true,
8673		expectedError: ":ERROR_PARSING_EXTENSION:",
8674	})
8675
8676	// Test that illegal extensions in TLS 1.3 are declined by the server if
8677	// offered in ClientHello. The runner's server will fail if this occurs,
8678	// so we exercise the offering path. (EMS and Renegotiation Info are
8679	// implicit in every test.)
8680	testCases = append(testCases, testCase{
8681		testType: serverTest,
8682		name:     "NPN-Declined-TLS13",
8683		config: Config{
8684			MaxVersion: VersionTLS13,
8685			NextProtos: []string{"bar"},
8686		},
8687		flags: []string{"-advertise-npn", "\x03foo\x03bar\x03baz"},
8688	})
8689
8690	// OpenSSL sends the status_request extension on resumption in TLS 1.2. Test that this is
8691	// tolerated.
8692	testCases = append(testCases, testCase{
8693		name: "SendOCSPResponseOnResume-TLS12",
8694		config: Config{
8695			MaxVersion: VersionTLS12,
8696			Credential: rsaCertificate.WithOCSP(testOCSPResponse),
8697			Bugs: ProtocolBugs{
8698				SendOCSPResponseOnResume: []byte("bogus"),
8699			},
8700		},
8701		flags: []string{
8702			"-enable-ocsp-stapling",
8703			"-expect-ocsp-response",
8704			base64FlagValue(testOCSPResponse),
8705		},
8706		resumeSession: true,
8707	})
8708
8709	testCases = append(testCases, testCase{
8710		name: "SendUnsolicitedOCSPOnCertificate-TLS13",
8711		config: Config{
8712			MaxVersion: VersionTLS13,
8713			Bugs: ProtocolBugs{
8714				SendExtensionOnCertificate: testOCSPExtension,
8715			},
8716		},
8717		shouldFail:    true,
8718		expectedError: ":UNEXPECTED_EXTENSION:",
8719	})
8720
8721	testCases = append(testCases, testCase{
8722		name: "SendUnsolicitedSCTOnCertificate-TLS13",
8723		config: Config{
8724			MaxVersion: VersionTLS13,
8725			Bugs: ProtocolBugs{
8726				SendExtensionOnCertificate: testSCTExtension,
8727			},
8728		},
8729		shouldFail:    true,
8730		expectedError: ":UNEXPECTED_EXTENSION:",
8731	})
8732
8733	// Test that extensions on client certificates are never accepted.
8734	testCases = append(testCases, testCase{
8735		name:     "SendExtensionOnClientCertificate-TLS13",
8736		testType: serverTest,
8737		config: Config{
8738			MaxVersion: VersionTLS13,
8739			Credential: &rsaCertificate,
8740			Bugs: ProtocolBugs{
8741				SendExtensionOnCertificate: testOCSPExtension,
8742			},
8743		},
8744		flags: []string{
8745			"-enable-ocsp-stapling",
8746			"-require-any-client-certificate",
8747		},
8748		shouldFail:    true,
8749		expectedError: ":UNEXPECTED_EXTENSION:",
8750	})
8751
8752	testCases = append(testCases, testCase{
8753		name: "SendUnknownExtensionOnCertificate-TLS13",
8754		config: Config{
8755			MaxVersion: VersionTLS13,
8756			Bugs: ProtocolBugs{
8757				SendExtensionOnCertificate: []byte{0x00, 0x7f, 0, 0},
8758			},
8759		},
8760		shouldFail:    true,
8761		expectedError: ":UNEXPECTED_EXTENSION:",
8762	})
8763
8764	// Test that extensions on intermediates are allowed but ignored.
8765	testCases = append(testCases, testCase{
8766		name: "IgnoreExtensionsOnIntermediates-TLS13",
8767		config: Config{
8768			MaxVersion: VersionTLS13,
8769			Credential: rsaChainCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
8770			Bugs: ProtocolBugs{
8771				// Send different values on the intermediate. This tests
8772				// the intermediate's extensions do not override the
8773				// leaf's.
8774				SendOCSPOnIntermediates: testOCSPResponse2,
8775				SendSCTOnIntermediates:  testSCTList2,
8776			},
8777		},
8778		flags: []string{
8779			"-enable-ocsp-stapling",
8780			"-expect-ocsp-response",
8781			base64FlagValue(testOCSPResponse),
8782			"-enable-signed-cert-timestamps",
8783			"-expect-signed-cert-timestamps",
8784			base64FlagValue(testSCTList),
8785		},
8786		resumeSession: true,
8787	})
8788
8789	// Test that extensions are not sent on intermediates when configured
8790	// only for a leaf.
8791	testCases = append(testCases, testCase{
8792		testType: serverTest,
8793		name:     "SendNoExtensionsOnIntermediate-TLS13",
8794		config: Config{
8795			MaxVersion: VersionTLS13,
8796			Bugs: ProtocolBugs{
8797				ExpectNoExtensionsOnIntermediate: true,
8798			},
8799		},
8800		shimCertificate: rsaChainCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
8801	})
8802
8803	// Test that extensions are not sent on client certificates.
8804	testCases = append(testCases, testCase{
8805		name: "SendNoClientCertificateExtensions-TLS13",
8806		config: Config{
8807			MaxVersion: VersionTLS13,
8808			ClientAuth: RequireAnyClientCert,
8809		},
8810		shimCertificate: rsaChainCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
8811	})
8812
8813	testCases = append(testCases, testCase{
8814		name: "SendDuplicateExtensionsOnCerts-TLS13",
8815		config: Config{
8816			MaxVersion: VersionTLS13,
8817			Credential: rsaCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
8818			Bugs: ProtocolBugs{
8819				SendDuplicateCertExtensions: true,
8820			},
8821		},
8822		flags: []string{
8823			"-enable-ocsp-stapling",
8824			"-enable-signed-cert-timestamps",
8825		},
8826		resumeSession: true,
8827		shouldFail:    true,
8828		expectedError: ":DUPLICATE_EXTENSION:",
8829	})
8830
8831	testCases = append(testCases, testCase{
8832		name:            "SignedCertificateTimestampListInvalid-Server",
8833		testType:        serverTest,
8834		shimCertificate: rsaCertificate.WithSCTList([]byte{0, 0}),
8835		shouldFail:      true,
8836		expectedError:   ":INVALID_SCT_LIST:",
8837	})
8838}
8839
8840func addResumptionVersionTests() {
8841	for _, sessionVers := range tlsVersions {
8842		for _, resumeVers := range tlsVersions {
8843			protocols := []protocol{tls}
8844			if sessionVers.hasDTLS && resumeVers.hasDTLS {
8845				protocols = append(protocols, dtls)
8846			}
8847			if sessionVers.hasQUIC && resumeVers.hasQUIC {
8848				protocols = append(protocols, quic)
8849			}
8850			for _, protocol := range protocols {
8851				suffix := "-" + sessionVers.name + "-" + resumeVers.name
8852				suffix += "-" + protocol.String()
8853
8854				if sessionVers.version == resumeVers.version {
8855					testCases = append(testCases, testCase{
8856						protocol:      protocol,
8857						name:          "Resume-Client" + suffix,
8858						resumeSession: true,
8859						config: Config{
8860							MaxVersion: sessionVers.version,
8861							Bugs: ProtocolBugs{
8862								ExpectNoTLS13PSK: sessionVers.version < VersionTLS13,
8863							},
8864						},
8865						expectations: connectionExpectations{
8866							version: sessionVers.version,
8867						},
8868						resumeExpectations: &connectionExpectations{
8869							version: resumeVers.version,
8870						},
8871					})
8872				} else {
8873					testCases = append(testCases, testCase{
8874						protocol:      protocol,
8875						name:          "Resume-Client-Mismatch" + suffix,
8876						resumeSession: true,
8877						config: Config{
8878							MaxVersion: sessionVers.version,
8879						},
8880						expectations: connectionExpectations{
8881							version: sessionVers.version,
8882						},
8883						resumeConfig: &Config{
8884							MaxVersion: resumeVers.version,
8885							Bugs: ProtocolBugs{
8886								AcceptAnySession: true,
8887							},
8888						},
8889						resumeExpectations: &connectionExpectations{
8890							version: resumeVers.version,
8891						},
8892						shouldFail:    true,
8893						expectedError: ":OLD_SESSION_VERSION_NOT_RETURNED:",
8894					})
8895				}
8896
8897				testCases = append(testCases, testCase{
8898					protocol:      protocol,
8899					name:          "Resume-Client-NoResume" + suffix,
8900					resumeSession: true,
8901					config: Config{
8902						MaxVersion: sessionVers.version,
8903					},
8904					expectations: connectionExpectations{
8905						version: sessionVers.version,
8906					},
8907					resumeConfig: &Config{
8908						MaxVersion: resumeVers.version,
8909					},
8910					newSessionsOnResume:  true,
8911					expectResumeRejected: true,
8912					resumeExpectations: &connectionExpectations{
8913						version: resumeVers.version,
8914					},
8915				})
8916
8917				testCases = append(testCases, testCase{
8918					protocol:      protocol,
8919					testType:      serverTest,
8920					name:          "Resume-Server" + suffix,
8921					resumeSession: true,
8922					config: Config{
8923						MaxVersion: sessionVers.version,
8924					},
8925					expectations: connectionExpectations{
8926						version: sessionVers.version,
8927					},
8928					expectResumeRejected: sessionVers != resumeVers,
8929					resumeConfig: &Config{
8930						MaxVersion: resumeVers.version,
8931						Bugs: ProtocolBugs{
8932							SendBothTickets: true,
8933						},
8934					},
8935					resumeExpectations: &connectionExpectations{
8936						version: resumeVers.version,
8937					},
8938				})
8939
8940				// Repeat the test using session IDs, rather than tickets.
8941				if sessionVers.version < VersionTLS13 && resumeVers.version < VersionTLS13 {
8942					testCases = append(testCases, testCase{
8943						protocol:      protocol,
8944						testType:      serverTest,
8945						name:          "Resume-Server-NoTickets" + suffix,
8946						resumeSession: true,
8947						config: Config{
8948							MaxVersion:             sessionVers.version,
8949							SessionTicketsDisabled: true,
8950						},
8951						expectations: connectionExpectations{
8952							version: sessionVers.version,
8953						},
8954						expectResumeRejected: sessionVers != resumeVers,
8955						resumeConfig: &Config{
8956							MaxVersion:             resumeVers.version,
8957							SessionTicketsDisabled: true,
8958						},
8959						resumeExpectations: &connectionExpectations{
8960							version: resumeVers.version,
8961						},
8962					})
8963				}
8964			}
8965		}
8966	}
8967
8968	// Make sure shim ticket mutations are functional.
8969	testCases = append(testCases, testCase{
8970		testType:      serverTest,
8971		name:          "ShimTicketRewritable",
8972		resumeSession: true,
8973		config: Config{
8974			MaxVersion:   VersionTLS12,
8975			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
8976			Bugs: ProtocolBugs{
8977				FilterTicket: func(in []byte) ([]byte, error) {
8978					in, err := SetShimTicketVersion(in, VersionTLS12)
8979					if err != nil {
8980						return nil, err
8981					}
8982					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
8983				},
8984			},
8985		},
8986		flags: []string{
8987			"-ticket-key",
8988			base64FlagValue(TestShimTicketKey),
8989		},
8990	})
8991
8992	// Resumptions are declined if the version does not match.
8993	testCases = append(testCases, testCase{
8994		testType:      serverTest,
8995		name:          "Resume-Server-DeclineCrossVersion",
8996		resumeSession: true,
8997		config: Config{
8998			MaxVersion: VersionTLS12,
8999			Bugs: ProtocolBugs{
9000				ExpectNewTicket: true,
9001				FilterTicket: func(in []byte) ([]byte, error) {
9002					return SetShimTicketVersion(in, VersionTLS13)
9003				},
9004			},
9005		},
9006		flags: []string{
9007			"-ticket-key",
9008			base64FlagValue(TestShimTicketKey),
9009		},
9010		expectResumeRejected: true,
9011	})
9012
9013	testCases = append(testCases, testCase{
9014		testType:      serverTest,
9015		name:          "Resume-Server-DeclineCrossVersion-TLS13",
9016		resumeSession: true,
9017		config: Config{
9018			MaxVersion: VersionTLS13,
9019			Bugs: ProtocolBugs{
9020				FilterTicket: func(in []byte) ([]byte, error) {
9021					return SetShimTicketVersion(in, VersionTLS12)
9022				},
9023			},
9024		},
9025		flags: []string{
9026			"-ticket-key",
9027			base64FlagValue(TestShimTicketKey),
9028		},
9029		expectResumeRejected: true,
9030	})
9031
9032	// Resumptions are declined if the cipher is invalid or disabled.
9033	testCases = append(testCases, testCase{
9034		testType:      serverTest,
9035		name:          "Resume-Server-DeclineBadCipher",
9036		resumeSession: true,
9037		config: Config{
9038			MaxVersion: VersionTLS12,
9039			Bugs: ProtocolBugs{
9040				ExpectNewTicket: true,
9041				FilterTicket: func(in []byte) ([]byte, error) {
9042					return SetShimTicketCipherSuite(in, TLS_AES_128_GCM_SHA256)
9043				},
9044			},
9045		},
9046		flags: []string{
9047			"-ticket-key",
9048			base64FlagValue(TestShimTicketKey),
9049		},
9050		expectResumeRejected: true,
9051	})
9052
9053	testCases = append(testCases, testCase{
9054		testType:      serverTest,
9055		name:          "Resume-Server-DeclineBadCipher-2",
9056		resumeSession: true,
9057		config: Config{
9058			MaxVersion: VersionTLS12,
9059			Bugs: ProtocolBugs{
9060				ExpectNewTicket: true,
9061				FilterTicket: func(in []byte) ([]byte, error) {
9062					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)
9063				},
9064			},
9065		},
9066		flags: []string{
9067			"-cipher", "AES128",
9068			"-ticket-key",
9069			base64FlagValue(TestShimTicketKey),
9070		},
9071		expectResumeRejected: true,
9072	})
9073
9074	// Sessions are not resumed if they do not use the preferred cipher.
9075	testCases = append(testCases, testCase{
9076		testType:      serverTest,
9077		name:          "Resume-Server-CipherNotPreferred",
9078		resumeSession: true,
9079		config: Config{
9080			MaxVersion: VersionTLS12,
9081			Bugs: ProtocolBugs{
9082				ExpectNewTicket: true,
9083				FilterTicket: func(in []byte) ([]byte, error) {
9084					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA)
9085				},
9086			},
9087		},
9088		flags: []string{
9089			"-ticket-key",
9090			base64FlagValue(TestShimTicketKey),
9091		},
9092		shouldFail:           false,
9093		expectResumeRejected: true,
9094	})
9095
9096	// TLS 1.3 allows sessions to be resumed at a different cipher if their
9097	// PRF hashes match, but BoringSSL will always decline such resumptions.
9098	testCases = append(testCases, testCase{
9099		testType:      serverTest,
9100		name:          "Resume-Server-CipherNotPreferred-TLS13",
9101		resumeSession: true,
9102		config: Config{
9103			MaxVersion:   VersionTLS13,
9104			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256, TLS_AES_128_GCM_SHA256},
9105			Bugs: ProtocolBugs{
9106				FilterTicket: func(in []byte) ([]byte, error) {
9107					// If the client (runner) offers ChaCha20-Poly1305 first, the
9108					// server (shim) always prefers it. Switch it to AES-GCM.
9109					return SetShimTicketCipherSuite(in, TLS_AES_128_GCM_SHA256)
9110				},
9111			},
9112		},
9113		flags: []string{
9114			"-ticket-key",
9115			base64FlagValue(TestShimTicketKey),
9116		},
9117		shouldFail:           false,
9118		expectResumeRejected: true,
9119	})
9120
9121	// Sessions may not be resumed if they contain another version's cipher.
9122	testCases = append(testCases, testCase{
9123		testType:      serverTest,
9124		name:          "Resume-Server-DeclineBadCipher-TLS13",
9125		resumeSession: true,
9126		config: Config{
9127			MaxVersion: VersionTLS13,
9128			Bugs: ProtocolBugs{
9129				FilterTicket: func(in []byte) ([]byte, error) {
9130					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
9131				},
9132			},
9133		},
9134		flags: []string{
9135			"-ticket-key",
9136			base64FlagValue(TestShimTicketKey),
9137		},
9138		expectResumeRejected: true,
9139	})
9140
9141	// If the client does not offer the cipher from the session, decline to
9142	// resume. Clients are forbidden from doing this, but BoringSSL selects
9143	// the cipher first, so we only decline.
9144	testCases = append(testCases, testCase{
9145		testType:      serverTest,
9146		name:          "Resume-Server-UnofferedCipher",
9147		resumeSession: true,
9148		config: Config{
9149			MaxVersion:   VersionTLS12,
9150			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
9151		},
9152		resumeConfig: &Config{
9153			MaxVersion:   VersionTLS12,
9154			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
9155			Bugs: ProtocolBugs{
9156				SendCipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
9157			},
9158		},
9159		expectResumeRejected: true,
9160	})
9161
9162	// In TLS 1.3, clients may advertise a cipher list which does not
9163	// include the selected cipher. Test that we tolerate this. Servers may
9164	// resume at another cipher if the PRF matches and are not doing 0-RTT, but
9165	// BoringSSL will always decline.
9166	testCases = append(testCases, testCase{
9167		testType:      serverTest,
9168		name:          "Resume-Server-UnofferedCipher-TLS13",
9169		resumeSession: true,
9170		config: Config{
9171			MaxVersion:   VersionTLS13,
9172			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
9173		},
9174		resumeConfig: &Config{
9175			MaxVersion:   VersionTLS13,
9176			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
9177			Bugs: ProtocolBugs{
9178				SendCipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
9179			},
9180		},
9181		expectResumeRejected: true,
9182	})
9183
9184	// Sessions may not be resumed at a different cipher.
9185	testCases = append(testCases, testCase{
9186		name:          "Resume-Client-CipherMismatch",
9187		resumeSession: true,
9188		config: Config{
9189			MaxVersion:   VersionTLS12,
9190			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
9191		},
9192		resumeConfig: &Config{
9193			MaxVersion:   VersionTLS12,
9194			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
9195			Bugs: ProtocolBugs{
9196				SendCipherSuite: TLS_RSA_WITH_AES_128_CBC_SHA,
9197			},
9198		},
9199		shouldFail:    true,
9200		expectedError: ":OLD_SESSION_CIPHER_NOT_RETURNED:",
9201	})
9202
9203	// Session resumption in TLS 1.3 may change the cipher suite if the PRF
9204	// matches.
9205	testCases = append(testCases, testCase{
9206		name:          "Resume-Client-CipherMismatch-TLS13",
9207		resumeSession: true,
9208		config: Config{
9209			MaxVersion:   VersionTLS13,
9210			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
9211		},
9212		resumeConfig: &Config{
9213			MaxVersion:   VersionTLS13,
9214			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
9215		},
9216	})
9217
9218	// Session resumption in TLS 1.3 is forbidden if the PRF does not match.
9219	testCases = append(testCases, testCase{
9220		name:          "Resume-Client-PRFMismatch-TLS13",
9221		resumeSession: true,
9222		config: Config{
9223			MaxVersion:   VersionTLS13,
9224			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
9225		},
9226		resumeConfig: &Config{
9227			MaxVersion:   VersionTLS13,
9228			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
9229			Bugs: ProtocolBugs{
9230				SendCipherSuite: TLS_AES_256_GCM_SHA384,
9231			},
9232		},
9233		shouldFail:    true,
9234		expectedError: ":OLD_SESSION_PRF_HASH_MISMATCH:",
9235	})
9236
9237	for _, secondBinder := range []bool{false, true} {
9238		var suffix string
9239		var defaultCurves []CurveID
9240		if secondBinder {
9241			suffix = "-SecondBinder"
9242			// Force a HelloRetryRequest by predicting an empty curve list.
9243			defaultCurves = []CurveID{}
9244		}
9245
9246		testCases = append(testCases, testCase{
9247			testType:      serverTest,
9248			name:          "Resume-Server-BinderWrongLength" + suffix,
9249			resumeSession: true,
9250			config: Config{
9251				MaxVersion:    VersionTLS13,
9252				DefaultCurves: defaultCurves,
9253				Bugs: ProtocolBugs{
9254					SendShortPSKBinder:         true,
9255					OnlyCorruptSecondPSKBinder: secondBinder,
9256				},
9257			},
9258			shouldFail:         true,
9259			expectedLocalError: "remote error: error decrypting message",
9260			expectedError:      ":DIGEST_CHECK_FAILED:",
9261		})
9262
9263		testCases = append(testCases, testCase{
9264			testType:      serverTest,
9265			name:          "Resume-Server-NoPSKBinder" + suffix,
9266			resumeSession: true,
9267			config: Config{
9268				MaxVersion:    VersionTLS13,
9269				DefaultCurves: defaultCurves,
9270				Bugs: ProtocolBugs{
9271					SendNoPSKBinder:            true,
9272					OnlyCorruptSecondPSKBinder: secondBinder,
9273				},
9274			},
9275			shouldFail:         true,
9276			expectedLocalError: "remote error: error decoding message",
9277			expectedError:      ":DECODE_ERROR:",
9278		})
9279
9280		testCases = append(testCases, testCase{
9281			testType:      serverTest,
9282			name:          "Resume-Server-ExtraPSKBinder" + suffix,
9283			resumeSession: true,
9284			config: Config{
9285				MaxVersion:    VersionTLS13,
9286				DefaultCurves: defaultCurves,
9287				Bugs: ProtocolBugs{
9288					SendExtraPSKBinder:         true,
9289					OnlyCorruptSecondPSKBinder: secondBinder,
9290				},
9291			},
9292			shouldFail:         true,
9293			expectedLocalError: "remote error: illegal parameter",
9294			expectedError:      ":PSK_IDENTITY_BINDER_COUNT_MISMATCH:",
9295		})
9296
9297		testCases = append(testCases, testCase{
9298			testType:      serverTest,
9299			name:          "Resume-Server-ExtraIdentityNoBinder" + suffix,
9300			resumeSession: true,
9301			config: Config{
9302				MaxVersion:    VersionTLS13,
9303				DefaultCurves: defaultCurves,
9304				Bugs: ProtocolBugs{
9305					ExtraPSKIdentity:           true,
9306					OnlyCorruptSecondPSKBinder: secondBinder,
9307				},
9308			},
9309			shouldFail:         true,
9310			expectedLocalError: "remote error: illegal parameter",
9311			expectedError:      ":PSK_IDENTITY_BINDER_COUNT_MISMATCH:",
9312		})
9313
9314		testCases = append(testCases, testCase{
9315			testType:      serverTest,
9316			name:          "Resume-Server-InvalidPSKBinder" + suffix,
9317			resumeSession: true,
9318			config: Config{
9319				MaxVersion:    VersionTLS13,
9320				DefaultCurves: defaultCurves,
9321				Bugs: ProtocolBugs{
9322					SendInvalidPSKBinder:       true,
9323					OnlyCorruptSecondPSKBinder: secondBinder,
9324				},
9325			},
9326			shouldFail:         true,
9327			expectedLocalError: "remote error: error decrypting message",
9328			expectedError:      ":DIGEST_CHECK_FAILED:",
9329		})
9330
9331		testCases = append(testCases, testCase{
9332			testType:      serverTest,
9333			name:          "Resume-Server-PSKBinderFirstExtension" + suffix,
9334			resumeSession: true,
9335			config: Config{
9336				MaxVersion:    VersionTLS13,
9337				DefaultCurves: defaultCurves,
9338				Bugs: ProtocolBugs{
9339					PSKBinderFirst:             true,
9340					OnlyCorruptSecondPSKBinder: secondBinder,
9341				},
9342			},
9343			shouldFail:         true,
9344			expectedLocalError: "remote error: illegal parameter",
9345			expectedError:      ":PRE_SHARED_KEY_MUST_BE_LAST:",
9346		})
9347	}
9348
9349	testCases = append(testCases, testCase{
9350		testType:      serverTest,
9351		name:          "Resume-Server-OmitPSKsOnSecondClientHello",
9352		resumeSession: true,
9353		config: Config{
9354			MaxVersion:    VersionTLS13,
9355			DefaultCurves: []CurveID{},
9356			Bugs: ProtocolBugs{
9357				OmitPSKsOnSecondClientHello: true,
9358			},
9359		},
9360		shouldFail:         true,
9361		expectedLocalError: "remote error: illegal parameter",
9362		expectedError:      ":INCONSISTENT_CLIENT_HELLO:",
9363	})
9364}
9365
9366func addRenegotiationTests() {
9367	// Servers cannot renegotiate.
9368	testCases = append(testCases, testCase{
9369		testType: serverTest,
9370		name:     "Renegotiate-Server-Forbidden",
9371		config: Config{
9372			MaxVersion: VersionTLS12,
9373		},
9374		renegotiate:        1,
9375		shouldFail:         true,
9376		expectedError:      ":NO_RENEGOTIATION:",
9377		expectedLocalError: "remote error: no renegotiation",
9378	})
9379	// The server shouldn't echo the renegotiation extension unless
9380	// requested by the client.
9381	testCases = append(testCases, testCase{
9382		testType: serverTest,
9383		name:     "Renegotiate-Server-NoExt",
9384		config: Config{
9385			MaxVersion: VersionTLS12,
9386			Bugs: ProtocolBugs{
9387				NoRenegotiationInfo:      true,
9388				RequireRenegotiationInfo: true,
9389			},
9390		},
9391		shouldFail:         true,
9392		expectedLocalError: "renegotiation extension missing",
9393	})
9394	// The renegotiation SCSV should be sufficient for the server to echo
9395	// the extension.
9396	testCases = append(testCases, testCase{
9397		testType: serverTest,
9398		name:     "Renegotiate-Server-NoExt-SCSV",
9399		config: Config{
9400			MaxVersion: VersionTLS12,
9401			Bugs: ProtocolBugs{
9402				NoRenegotiationInfo:      true,
9403				SendRenegotiationSCSV:    true,
9404				RequireRenegotiationInfo: true,
9405			},
9406		},
9407	})
9408	testCases = append(testCases, testCase{
9409		name: "Renegotiate-Client",
9410		config: Config{
9411			MaxVersion: VersionTLS12,
9412			Bugs: ProtocolBugs{
9413				FailIfResumeOnRenego: true,
9414			},
9415		},
9416		renegotiate: 1,
9417		// Test renegotiation after both an initial and resumption
9418		// handshake.
9419		resumeSession: true,
9420		flags: []string{
9421			"-renegotiate-freely",
9422			"-expect-total-renegotiations", "1",
9423			"-expect-secure-renegotiation",
9424		},
9425	})
9426	testCases = append(testCases, testCase{
9427		name: "Renegotiate-Client-TLS12",
9428		config: Config{
9429			MaxVersion: VersionTLS12,
9430			Bugs: ProtocolBugs{
9431				FailIfResumeOnRenego: true,
9432			},
9433		},
9434		renegotiate: 1,
9435		// Test renegotiation after both an initial and resumption
9436		// handshake.
9437		resumeSession: true,
9438		flags: []string{
9439			"-renegotiate-freely",
9440			"-expect-total-renegotiations", "1",
9441			"-expect-secure-renegotiation",
9442		},
9443	})
9444	testCases = append(testCases, testCase{
9445		name:        "Renegotiate-Client-EmptyExt",
9446		renegotiate: 1,
9447		config: Config{
9448			MaxVersion: VersionTLS12,
9449			Bugs: ProtocolBugs{
9450				EmptyRenegotiationInfo: true,
9451			},
9452		},
9453		flags:              []string{"-renegotiate-freely"},
9454		shouldFail:         true,
9455		expectedError:      ":RENEGOTIATION_MISMATCH:",
9456		expectedLocalError: "handshake failure",
9457	})
9458	testCases = append(testCases, testCase{
9459		name:        "Renegotiate-Client-BadExt",
9460		renegotiate: 1,
9461		config: Config{
9462			MaxVersion: VersionTLS12,
9463			Bugs: ProtocolBugs{
9464				BadRenegotiationInfo: true,
9465			},
9466		},
9467		flags:              []string{"-renegotiate-freely"},
9468		shouldFail:         true,
9469		expectedError:      ":RENEGOTIATION_MISMATCH:",
9470		expectedLocalError: "handshake failure",
9471	})
9472	testCases = append(testCases, testCase{
9473		name:        "Renegotiate-Client-BadExt2",
9474		renegotiate: 1,
9475		config: Config{
9476			MaxVersion: VersionTLS12,
9477			Bugs: ProtocolBugs{
9478				BadRenegotiationInfoEnd: true,
9479			},
9480		},
9481		flags:              []string{"-renegotiate-freely"},
9482		shouldFail:         true,
9483		expectedError:      ":RENEGOTIATION_MISMATCH:",
9484		expectedLocalError: "handshake failure",
9485	})
9486	testCases = append(testCases, testCase{
9487		name:        "Renegotiate-Client-Downgrade",
9488		renegotiate: 1,
9489		config: Config{
9490			MaxVersion: VersionTLS12,
9491			Bugs: ProtocolBugs{
9492				NoRenegotiationInfoAfterInitial: true,
9493			},
9494		},
9495		flags:              []string{"-renegotiate-freely"},
9496		shouldFail:         true,
9497		expectedError:      ":RENEGOTIATION_MISMATCH:",
9498		expectedLocalError: "handshake failure",
9499	})
9500	testCases = append(testCases, testCase{
9501		name:        "Renegotiate-Client-Upgrade",
9502		renegotiate: 1,
9503		config: Config{
9504			MaxVersion: VersionTLS12,
9505			Bugs: ProtocolBugs{
9506				NoRenegotiationInfoInInitial: true,
9507			},
9508		},
9509		flags:              []string{"-renegotiate-freely"},
9510		shouldFail:         true,
9511		expectedError:      ":RENEGOTIATION_MISMATCH:",
9512		expectedLocalError: "handshake failure",
9513	})
9514	testCases = append(testCases, testCase{
9515		name:        "Renegotiate-Client-NoExt-Allowed",
9516		renegotiate: 1,
9517		config: Config{
9518			MaxVersion: VersionTLS12,
9519			Bugs: ProtocolBugs{
9520				NoRenegotiationInfo: true,
9521			},
9522		},
9523		flags: []string{
9524			"-renegotiate-freely",
9525			"-expect-total-renegotiations", "1",
9526			"-expect-no-secure-renegotiation",
9527		},
9528	})
9529
9530	// Test that the server may switch ciphers on renegotiation without
9531	// problems.
9532	testCases = append(testCases, testCase{
9533		name:        "Renegotiate-Client-SwitchCiphers",
9534		renegotiate: 1,
9535		config: Config{
9536			MaxVersion:   VersionTLS12,
9537			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
9538		},
9539		renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
9540		flags: []string{
9541			"-renegotiate-freely",
9542			"-expect-total-renegotiations", "1",
9543		},
9544	})
9545	testCases = append(testCases, testCase{
9546		name:        "Renegotiate-Client-SwitchCiphers2",
9547		renegotiate: 1,
9548		config: Config{
9549			MaxVersion:   VersionTLS12,
9550			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
9551		},
9552		renegotiateCiphers: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
9553		flags: []string{
9554			"-renegotiate-freely",
9555			"-expect-total-renegotiations", "1",
9556		},
9557	})
9558
9559	// Test that the server may not switch versions on renegotiation.
9560	testCases = append(testCases, testCase{
9561		name: "Renegotiate-Client-SwitchVersion",
9562		config: Config{
9563			MaxVersion: VersionTLS12,
9564			// Pick a cipher which exists at both versions.
9565			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
9566			Bugs: ProtocolBugs{
9567				NegotiateVersionOnRenego: VersionTLS11,
9568				// Avoid failing early at the record layer.
9569				SendRecordVersion: VersionTLS12,
9570			},
9571		},
9572		renegotiate: 1,
9573		flags: []string{
9574			"-renegotiate-freely",
9575			"-expect-total-renegotiations", "1",
9576		},
9577		shouldFail:    true,
9578		expectedError: ":WRONG_SSL_VERSION:",
9579	})
9580
9581	testCases = append(testCases, testCase{
9582		name:        "Renegotiate-SameClientVersion",
9583		renegotiate: 1,
9584		config: Config{
9585			MaxVersion: VersionTLS10,
9586			Bugs: ProtocolBugs{
9587				RequireSameRenegoClientVersion: true,
9588			},
9589		},
9590		flags: []string{
9591			"-renegotiate-freely",
9592			"-expect-total-renegotiations", "1",
9593		},
9594	})
9595	testCases = append(testCases, testCase{
9596		name:        "Renegotiate-FalseStart",
9597		renegotiate: 1,
9598		config: Config{
9599			MaxVersion:   VersionTLS12,
9600			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
9601			NextProtos:   []string{"foo"},
9602		},
9603		flags: []string{
9604			"-false-start",
9605			"-select-next-proto", "foo",
9606			"-renegotiate-freely",
9607			"-expect-total-renegotiations", "1",
9608		},
9609		shimWritesFirst: true,
9610	})
9611
9612	// Client-side renegotiation controls.
9613	testCases = append(testCases, testCase{
9614		name: "Renegotiate-Client-Forbidden-1",
9615		config: Config{
9616			MaxVersion: VersionTLS12,
9617		},
9618		renegotiate:        1,
9619		shouldFail:         true,
9620		expectedError:      ":NO_RENEGOTIATION:",
9621		expectedLocalError: "remote error: no renegotiation",
9622	})
9623	testCases = append(testCases, testCase{
9624		name: "Renegotiate-Client-Once-1",
9625		config: Config{
9626			MaxVersion: VersionTLS12,
9627		},
9628		renegotiate: 1,
9629		flags: []string{
9630			"-renegotiate-once",
9631			"-expect-total-renegotiations", "1",
9632		},
9633	})
9634	testCases = append(testCases, testCase{
9635		name: "Renegotiate-Client-Freely-1",
9636		config: Config{
9637			MaxVersion: VersionTLS12,
9638		},
9639		renegotiate: 1,
9640		flags: []string{
9641			"-renegotiate-freely",
9642			"-expect-total-renegotiations", "1",
9643		},
9644	})
9645	testCases = append(testCases, testCase{
9646		name: "Renegotiate-Client-Once-2",
9647		config: Config{
9648			MaxVersion: VersionTLS12,
9649		},
9650		renegotiate:        2,
9651		flags:              []string{"-renegotiate-once"},
9652		shouldFail:         true,
9653		expectedError:      ":NO_RENEGOTIATION:",
9654		expectedLocalError: "remote error: no renegotiation",
9655	})
9656	testCases = append(testCases, testCase{
9657		name: "Renegotiate-Client-Freely-2",
9658		config: Config{
9659			MaxVersion: VersionTLS12,
9660		},
9661		renegotiate: 2,
9662		flags: []string{
9663			"-renegotiate-freely",
9664			"-expect-total-renegotiations", "2",
9665		},
9666	})
9667	testCases = append(testCases, testCase{
9668		name: "Renegotiate-Client-NoIgnore",
9669		config: Config{
9670			MaxVersion: VersionTLS12,
9671			Bugs: ProtocolBugs{
9672				SendHelloRequestBeforeEveryAppDataRecord: true,
9673			},
9674		},
9675		shouldFail:    true,
9676		expectedError: ":NO_RENEGOTIATION:",
9677	})
9678	testCases = append(testCases, testCase{
9679		name: "Renegotiate-Client-Ignore",
9680		config: Config{
9681			MaxVersion: VersionTLS12,
9682			Bugs: ProtocolBugs{
9683				SendHelloRequestBeforeEveryAppDataRecord: true,
9684			},
9685		},
9686		flags: []string{
9687			"-renegotiate-ignore",
9688			"-expect-total-renegotiations", "0",
9689		},
9690	})
9691
9692	// Renegotiation may be enabled and then disabled immediately after the
9693	// handshake.
9694	testCases = append(testCases, testCase{
9695		name: "Renegotiate-ForbidAfterHandshake",
9696		config: Config{
9697			MaxVersion: VersionTLS12,
9698		},
9699		renegotiate:        1,
9700		flags:              []string{"-forbid-renegotiation-after-handshake"},
9701		shouldFail:         true,
9702		expectedError:      ":NO_RENEGOTIATION:",
9703		expectedLocalError: "remote error: no renegotiation",
9704	})
9705
9706	// Renegotiation is not allowed when there is an unfinished write.
9707	testCases = append(testCases, testCase{
9708		name: "Renegotiate-Client-UnfinishedWrite",
9709		config: Config{
9710			MaxVersion: VersionTLS12,
9711		},
9712		renegotiate:             1,
9713		readWithUnfinishedWrite: true,
9714		flags: []string{
9715			"-async",
9716			"-renegotiate-freely",
9717		},
9718		shouldFail:    true,
9719		expectedError: ":NO_RENEGOTIATION:",
9720		// We do not successfully send the no_renegotiation alert in
9721		// this case. https://crbug.com/boringssl/130
9722	})
9723
9724	// We reject stray HelloRequests during the handshake in TLS 1.2.
9725	testCases = append(testCases, testCase{
9726		name: "StrayHelloRequest",
9727		config: Config{
9728			MaxVersion: VersionTLS12,
9729			Bugs: ProtocolBugs{
9730				SendHelloRequestBeforeEveryHandshakeMessage: true,
9731			},
9732		},
9733		shouldFail:    true,
9734		expectedError: ":UNEXPECTED_MESSAGE:",
9735	})
9736	testCases = append(testCases, testCase{
9737		name: "StrayHelloRequest-Packed",
9738		config: Config{
9739			MaxVersion: VersionTLS12,
9740			Bugs: ProtocolBugs{
9741				PackHandshakeFlight:                         true,
9742				SendHelloRequestBeforeEveryHandshakeMessage: true,
9743			},
9744		},
9745		shouldFail:    true,
9746		expectedError: ":UNEXPECTED_MESSAGE:",
9747	})
9748
9749	// Test that HelloRequest is rejected if it comes in the same record as the
9750	// server Finished.
9751	testCases = append(testCases, testCase{
9752		name: "Renegotiate-Client-Packed",
9753		config: Config{
9754			MaxVersion: VersionTLS12,
9755			Bugs: ProtocolBugs{
9756				PackHandshakeFlight:          true,
9757				PackHelloRequestWithFinished: true,
9758			},
9759		},
9760		renegotiate:        1,
9761		flags:              []string{"-renegotiate-freely"},
9762		shouldFail:         true,
9763		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
9764		expectedLocalError: "remote error: unexpected message",
9765	})
9766
9767	// Renegotiation is forbidden in TLS 1.3.
9768	testCases = append(testCases, testCase{
9769		name: "Renegotiate-Client-TLS13",
9770		config: Config{
9771			MaxVersion: VersionTLS13,
9772			Bugs: ProtocolBugs{
9773				SendHelloRequestBeforeEveryAppDataRecord: true,
9774			},
9775		},
9776		flags: []string{
9777			"-renegotiate-freely",
9778		},
9779		shouldFail:    true,
9780		expectedError: ":UNEXPECTED_MESSAGE:",
9781	})
9782
9783	// Stray HelloRequests during the handshake are forbidden in TLS 1.3.
9784	testCases = append(testCases, testCase{
9785		name: "StrayHelloRequest-TLS13",
9786		config: Config{
9787			MaxVersion: VersionTLS13,
9788			Bugs: ProtocolBugs{
9789				SendHelloRequestBeforeEveryHandshakeMessage: true,
9790			},
9791		},
9792		shouldFail:    true,
9793		expectedError: ":UNEXPECTED_MESSAGE:",
9794	})
9795
9796	// The renegotiation_info extension is not sent in TLS 1.3, but TLS 1.3
9797	// always reads as supporting it, regardless of whether it was
9798	// negotiated.
9799	testCases = append(testCases, testCase{
9800		name: "AlwaysReportRenegotiationInfo-TLS13",
9801		config: Config{
9802			MaxVersion: VersionTLS13,
9803			Bugs: ProtocolBugs{
9804				NoRenegotiationInfo: true,
9805			},
9806		},
9807		flags: []string{
9808			"-expect-secure-renegotiation",
9809		},
9810	})
9811
9812	// Certificates may not change on renegotiation.
9813	testCases = append(testCases, testCase{
9814		name: "Renegotiation-CertificateChange",
9815		config: Config{
9816			MaxVersion: VersionTLS12,
9817			Credential: &rsaCertificate,
9818			Bugs: ProtocolBugs{
9819				RenegotiationCertificate: &rsaChainCertificate,
9820			},
9821		},
9822		renegotiate:   1,
9823		flags:         []string{"-renegotiate-freely"},
9824		shouldFail:    true,
9825		expectedError: ":SERVER_CERT_CHANGED:",
9826	})
9827	testCases = append(testCases, testCase{
9828		name: "Renegotiation-CertificateChange-2",
9829		config: Config{
9830			MaxVersion: VersionTLS12,
9831			Credential: &rsaCertificate,
9832			Bugs: ProtocolBugs{
9833				RenegotiationCertificate: &rsa1024Certificate,
9834			},
9835		},
9836		renegotiate:   1,
9837		flags:         []string{"-renegotiate-freely"},
9838		shouldFail:    true,
9839		expectedError: ":SERVER_CERT_CHANGED:",
9840	})
9841
9842	// We do not negotiate ALPN after the initial handshake. This is
9843	// error-prone and only risks bugs in consumers.
9844	testCases = append(testCases, testCase{
9845		testType: clientTest,
9846		name:     "Renegotiation-ForbidALPN",
9847		config: Config{
9848			MaxVersion: VersionTLS12,
9849			Bugs: ProtocolBugs{
9850				// Forcibly negotiate ALPN on both initial and
9851				// renegotiation handshakes. The test stack will
9852				// internally check the client does not offer
9853				// it.
9854				SendALPN: "foo",
9855			},
9856		},
9857		flags: []string{
9858			"-advertise-alpn", "\x03foo\x03bar\x03baz",
9859			"-expect-alpn", "foo",
9860			"-renegotiate-freely",
9861		},
9862		renegotiate:   1,
9863		shouldFail:    true,
9864		expectedError: ":UNEXPECTED_EXTENSION:",
9865	})
9866
9867	// The server may send different stapled OCSP responses or SCT lists on
9868	// renegotiation, but BoringSSL ignores this and reports the old values.
9869	// Also test that non-fatal verify results are preserved.
9870	testCases = append(testCases, testCase{
9871		testType: clientTest,
9872		name:     "Renegotiation-ChangeAuthProperties",
9873		config: Config{
9874			MaxVersion: VersionTLS12,
9875			Credential: rsaCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
9876			Bugs: ProtocolBugs{
9877				SendOCSPResponseOnRenegotiation: testOCSPResponse2,
9878				SendSCTListOnRenegotiation:      testSCTList2,
9879			},
9880		},
9881		renegotiate: 1,
9882		flags: []string{
9883			"-renegotiate-freely",
9884			"-expect-total-renegotiations", "1",
9885			"-enable-ocsp-stapling",
9886			"-expect-ocsp-response",
9887			base64FlagValue(testOCSPResponse),
9888			"-enable-signed-cert-timestamps",
9889			"-expect-signed-cert-timestamps",
9890			base64FlagValue(testSCTList),
9891			"-verify-fail",
9892			"-expect-verify-result",
9893		},
9894	})
9895}
9896
9897func addDTLSReplayTests() {
9898	// Test that sequence number replays are detected.
9899	testCases = append(testCases, testCase{
9900		protocol:     dtls,
9901		name:         "DTLS-Replay",
9902		messageCount: 200,
9903		replayWrites: true,
9904	})
9905
9906	// Test the incoming sequence number skipping by values larger
9907	// than the retransmit window.
9908	testCases = append(testCases, testCase{
9909		protocol: dtls,
9910		name:     "DTLS-Replay-LargeGaps",
9911		config: Config{
9912			Bugs: ProtocolBugs{
9913				SequenceNumberMapping: func(in uint64) uint64 {
9914					return in * 1023
9915				},
9916			},
9917		},
9918		messageCount: 200,
9919		replayWrites: true,
9920	})
9921
9922	// Test the incoming sequence number changing non-monotonically.
9923	testCases = append(testCases, testCase{
9924		protocol: dtls,
9925		name:     "DTLS-Replay-NonMonotonic",
9926		config: Config{
9927			Bugs: ProtocolBugs{
9928				SequenceNumberMapping: func(in uint64) uint64 {
9929					// This mapping has numbers counting backwards in groups
9930					// of 256, and then jumping forwards 511 numbers.
9931					return in ^ 255
9932				},
9933			},
9934		},
9935		// This messageCount is large enough to make sure that the SequenceNumberMapping
9936		// will reach the point where it jumps forwards after stepping backwards.
9937		messageCount: 500,
9938		replayWrites: true,
9939	})
9940}
9941
9942var testSignatureAlgorithms = []struct {
9943	name     string
9944	id       signatureAlgorithm
9945	baseCert *Credential
9946	// If non-zero, the curve that must be supported in TLS 1.2 for cert to be
9947	// accepted.
9948	curve CurveID
9949}{
9950	{"RSA_PKCS1_SHA1", signatureRSAPKCS1WithSHA1, &rsaCertificate, 0},
9951	{"RSA_PKCS1_SHA256", signatureRSAPKCS1WithSHA256, &rsaCertificate, 0},
9952	{"RSA_PKCS1_SHA384", signatureRSAPKCS1WithSHA384, &rsaCertificate, 0},
9953	{"RSA_PKCS1_SHA512", signatureRSAPKCS1WithSHA512, &rsaCertificate, 0},
9954	{"ECDSA_SHA1", signatureECDSAWithSHA1, &ecdsaP256Certificate, CurveP256},
9955	// The “P256” in the following line is not a mistake. In TLS 1.2 the
9956	// hash function doesn't have to match the curve and so the same
9957	// signature algorithm works with P-224.
9958	{"ECDSA_P224_SHA256", signatureECDSAWithP256AndSHA256, &ecdsaP224Certificate, CurveP224},
9959	{"ECDSA_P256_SHA256", signatureECDSAWithP256AndSHA256, &ecdsaP256Certificate, CurveP256},
9960	{"ECDSA_P384_SHA384", signatureECDSAWithP384AndSHA384, &ecdsaP384Certificate, CurveP384},
9961	{"ECDSA_P521_SHA512", signatureECDSAWithP521AndSHA512, &ecdsaP521Certificate, CurveP521},
9962	{"RSA_PSS_SHA256", signatureRSAPSSWithSHA256, &rsaCertificate, 0},
9963	{"RSA_PSS_SHA384", signatureRSAPSSWithSHA384, &rsaCertificate, 0},
9964	{"RSA_PSS_SHA512", signatureRSAPSSWithSHA512, &rsaCertificate, 0},
9965	{"Ed25519", signatureEd25519, &ed25519Certificate, 0},
9966	// Tests for key types prior to TLS 1.2.
9967	{"RSA", 0, &rsaCertificate, 0},
9968	{"ECDSA", 0, &ecdsaP256Certificate, CurveP256},
9969}
9970
9971const fakeSigAlg1 signatureAlgorithm = 0x2a01
9972const fakeSigAlg2 signatureAlgorithm = 0xff01
9973
9974func addSignatureAlgorithmTests() {
9975	// Not all ciphers involve a signature. Advertise a list which gives all
9976	// versions a signing cipher.
9977	signingCiphers := []uint16{
9978		TLS_AES_256_GCM_SHA384,
9979		TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
9980		TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
9981		TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
9982		TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
9983	}
9984
9985	var allAlgorithms []signatureAlgorithm
9986	for _, alg := range testSignatureAlgorithms {
9987		if alg.id != 0 {
9988			allAlgorithms = append(allAlgorithms, alg.id)
9989		}
9990	}
9991
9992	// Make sure each signature algorithm works. Include some fake values in
9993	// the list and ensure they're ignored.
9994	for _, alg := range testSignatureAlgorithms {
9995		// Make a version of the certificate that will not sign any other algorithm.
9996		cert := alg.baseCert
9997		if alg.id != 0 {
9998			cert = cert.WithSignatureAlgorithms(alg.id)
9999		}
10000
10001		for _, ver := range tlsVersions {
10002			if (ver.version < VersionTLS12) != (alg.id == 0) {
10003				continue
10004			}
10005
10006			var shouldFail, rejectByDefault bool
10007			// ecdsa_sha1 does not exist in TLS 1.3.
10008			if ver.version >= VersionTLS13 && alg.id == signatureECDSAWithSHA1 {
10009				shouldFail = true
10010			}
10011			// RSA-PKCS1 does not exist in TLS 1.3.
10012			if ver.version >= VersionTLS13 && hasComponent(alg.name, "PKCS1") {
10013				shouldFail = true
10014			}
10015			// SHA-224 has been removed from TLS 1.3 and, in 1.3,
10016			// the curve has to match the hash size.
10017			if ver.version >= VersionTLS13 && alg.curve == CurveP224 {
10018				shouldFail = true
10019			}
10020
10021			// By default, BoringSSL does not enable ecdsa_sha1, ecdsa_secp521_sha512, and ed25519.
10022			if alg.id == signatureECDSAWithSHA1 || alg.id == signatureECDSAWithP521AndSHA512 || alg.id == signatureEd25519 {
10023				rejectByDefault = true
10024			}
10025
10026			var curveFlags []string
10027			var runnerCurves []CurveID
10028			if alg.curve != 0 && ver.version <= VersionTLS12 {
10029				// In TLS 1.2, the ECDH curve list also constrains ECDSA keys. Ensure the
10030				// corresponding curve is enabled. Also include X25519 to ensure the shim
10031				// and runner have something in common for ECDH.
10032				curveFlags = flagInts("-curves", []int{int(CurveX25519), int(alg.curve)})
10033				runnerCurves = []CurveID{CurveX25519, alg.curve}
10034			}
10035
10036			var signError, signLocalError, verifyError, verifyLocalError, defaultError, defaultLocalError string
10037			if shouldFail {
10038				signError = ":NO_COMMON_SIGNATURE_ALGORITHMS:"
10039				signLocalError = "remote error: handshake failure"
10040				verifyError = ":WRONG_SIGNATURE_TYPE:"
10041				verifyLocalError = "remote error"
10042				rejectByDefault = true
10043			}
10044			if rejectByDefault {
10045				defaultError = ":WRONG_SIGNATURE_TYPE:"
10046				defaultLocalError = "remote error"
10047			}
10048
10049			suffix := "-" + alg.name + "-" + ver.name
10050
10051			for _, testType := range []testType{clientTest, serverTest} {
10052				prefix := "Client-"
10053				if testType == serverTest {
10054					prefix = "Server-"
10055				}
10056
10057				// Test the shim using the algorithm for signing.
10058				signTest := testCase{
10059					testType: testType,
10060					name:     prefix + "Sign" + suffix,
10061					config: Config{
10062						MaxVersion:       ver.version,
10063						CurvePreferences: runnerCurves,
10064						VerifySignatureAlgorithms: []signatureAlgorithm{
10065							fakeSigAlg1,
10066							alg.id,
10067							fakeSigAlg2,
10068						},
10069					},
10070					shimCertificate:    cert,
10071					flags:              curveFlags,
10072					shouldFail:         shouldFail,
10073					expectedError:      signError,
10074					expectedLocalError: signLocalError,
10075					expectations: connectionExpectations{
10076						peerSignatureAlgorithm: alg.id,
10077					},
10078				}
10079
10080				// Test that the shim will select the algorithm when configured to only
10081				// support it.
10082				negotiateTest := testCase{
10083					testType: testType,
10084					name:     prefix + "Sign-Negotiate" + suffix,
10085					config: Config{
10086						MaxVersion:                ver.version,
10087						CurvePreferences:          runnerCurves,
10088						VerifySignatureAlgorithms: allAlgorithms,
10089					},
10090					shimCertificate: cert,
10091					flags:           curveFlags,
10092					expectations: connectionExpectations{
10093						peerSignatureAlgorithm: alg.id,
10094					},
10095				}
10096
10097				if testType == serverTest {
10098					// TLS 1.2 servers only sign on some cipher suites.
10099					signTest.config.CipherSuites = signingCiphers
10100					negotiateTest.config.CipherSuites = signingCiphers
10101				} else {
10102					// TLS 1.2 clients only sign when the server requests certificates.
10103					signTest.config.ClientAuth = RequireAnyClientCert
10104					negotiateTest.config.ClientAuth = RequireAnyClientCert
10105				}
10106				testCases = append(testCases, signTest)
10107				if ver.version >= VersionTLS12 && !shouldFail {
10108					testCases = append(testCases, negotiateTest)
10109				}
10110
10111				// Test the shim using the algorithm for verifying.
10112				verifyTest := testCase{
10113					testType: testType,
10114					name:     prefix + "Verify" + suffix,
10115					config: Config{
10116						MaxVersion: ver.version,
10117						Credential: cert,
10118						Bugs: ProtocolBugs{
10119							SkipECDSACurveCheck:          shouldFail,
10120							IgnoreSignatureVersionChecks: shouldFail,
10121							// Some signature algorithms may not be advertised.
10122							IgnorePeerSignatureAlgorithmPreferences: shouldFail,
10123						},
10124					},
10125					flags: curveFlags,
10126					// Resume the session to assert the peer signature
10127					// algorithm is reported on both handshakes.
10128					resumeSession:      !shouldFail,
10129					shouldFail:         shouldFail,
10130					expectedError:      verifyError,
10131					expectedLocalError: verifyLocalError,
10132				}
10133				if alg.id != 0 {
10134					verifyTest.flags = append(verifyTest.flags, "-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id)))
10135					// The algorithm may be disabled by default, so explicitly enable it.
10136					verifyTest.flags = append(verifyTest.flags, "-verify-prefs", strconv.Itoa(int(alg.id)))
10137				}
10138
10139				// Test whether the shim expects the algorithm enabled by default.
10140				defaultTest := testCase{
10141					testType: testType,
10142					name:     prefix + "VerifyDefault" + suffix,
10143					config: Config{
10144						MaxVersion: ver.version,
10145						Credential: cert,
10146						Bugs: ProtocolBugs{
10147							SkipECDSACurveCheck:          rejectByDefault,
10148							IgnoreSignatureVersionChecks: rejectByDefault,
10149							// Some signature algorithms may not be advertised.
10150							IgnorePeerSignatureAlgorithmPreferences: rejectByDefault,
10151						},
10152					},
10153					flags: append(
10154						[]string{"-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id))},
10155						curveFlags...,
10156					),
10157					// Resume the session to assert the peer signature
10158					// algorithm is reported on both handshakes.
10159					resumeSession:      !rejectByDefault,
10160					shouldFail:         rejectByDefault,
10161					expectedError:      defaultError,
10162					expectedLocalError: defaultLocalError,
10163				}
10164
10165				// Test whether the shim handles invalid signatures for this algorithm.
10166				invalidTest := testCase{
10167					testType: testType,
10168					name:     prefix + "InvalidSignature" + suffix,
10169					config: Config{
10170						MaxVersion: ver.version,
10171						Credential: cert,
10172						Bugs: ProtocolBugs{
10173							InvalidSignature: true,
10174						},
10175					},
10176					flags:         curveFlags,
10177					shouldFail:    true,
10178					expectedError: ":BAD_SIGNATURE:",
10179				}
10180				if alg.id != 0 {
10181					// The algorithm may be disabled by default, so explicitly enable it.
10182					invalidTest.flags = append(invalidTest.flags, "-verify-prefs", strconv.Itoa(int(alg.id)))
10183				}
10184
10185				if testType == serverTest {
10186					// TLS 1.2 servers only verify when they request client certificates.
10187					verifyTest.flags = append(verifyTest.flags, "-require-any-client-certificate")
10188					defaultTest.flags = append(defaultTest.flags, "-require-any-client-certificate")
10189					invalidTest.flags = append(invalidTest.flags, "-require-any-client-certificate")
10190				} else {
10191					// TLS 1.2 clients only verify on some cipher suites.
10192					verifyTest.config.CipherSuites = signingCiphers
10193					defaultTest.config.CipherSuites = signingCiphers
10194					invalidTest.config.CipherSuites = signingCiphers
10195				}
10196				testCases = append(testCases, verifyTest, defaultTest)
10197				if !shouldFail {
10198					testCases = append(testCases, invalidTest)
10199				}
10200			}
10201		}
10202	}
10203
10204	// Test the peer's verify preferences are available.
10205	for _, ver := range tlsVersions {
10206		if ver.version < VersionTLS12 {
10207			continue
10208		}
10209		testCases = append(testCases, testCase{
10210			name: "ClientAuth-PeerVerifyPrefs-" + ver.name,
10211			config: Config{
10212				MaxVersion: ver.version,
10213				ClientAuth: RequireAnyClientCert,
10214				VerifySignatureAlgorithms: []signatureAlgorithm{
10215					signatureRSAPSSWithSHA256,
10216					signatureEd25519,
10217					signatureECDSAWithP256AndSHA256,
10218				},
10219			},
10220			shimCertificate: &rsaCertificate,
10221			flags: []string{
10222				"-expect-peer-verify-pref", strconv.Itoa(int(signatureRSAPSSWithSHA256)),
10223				"-expect-peer-verify-pref", strconv.Itoa(int(signatureEd25519)),
10224				"-expect-peer-verify-pref", strconv.Itoa(int(signatureECDSAWithP256AndSHA256)),
10225			},
10226		})
10227
10228		testCases = append(testCases, testCase{
10229			testType: serverTest,
10230			name:     "ServerAuth-PeerVerifyPrefs-" + ver.name,
10231			config: Config{
10232				MaxVersion: ver.version,
10233				VerifySignatureAlgorithms: []signatureAlgorithm{
10234					signatureRSAPSSWithSHA256,
10235					signatureEd25519,
10236					signatureECDSAWithP256AndSHA256,
10237				},
10238			},
10239			shimCertificate: &rsaCertificate,
10240			flags: []string{
10241				"-expect-peer-verify-pref", strconv.Itoa(int(signatureRSAPSSWithSHA256)),
10242				"-expect-peer-verify-pref", strconv.Itoa(int(signatureEd25519)),
10243				"-expect-peer-verify-pref", strconv.Itoa(int(signatureECDSAWithP256AndSHA256)),
10244			},
10245		})
10246
10247	}
10248
10249	// Test that algorithm selection takes the key type into account.
10250	testCases = append(testCases, testCase{
10251		name: "ClientAuth-SignatureType",
10252		config: Config{
10253			ClientAuth: RequireAnyClientCert,
10254			MaxVersion: VersionTLS12,
10255			VerifySignatureAlgorithms: []signatureAlgorithm{
10256				signatureECDSAWithP521AndSHA512,
10257				signatureRSAPKCS1WithSHA384,
10258				signatureECDSAWithSHA1,
10259			},
10260		},
10261		shimCertificate: &rsaCertificate,
10262		expectations: connectionExpectations{
10263			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA384,
10264		},
10265	})
10266
10267	testCases = append(testCases, testCase{
10268		name: "ClientAuth-SignatureType-TLS13",
10269		config: Config{
10270			ClientAuth: RequireAnyClientCert,
10271			MaxVersion: VersionTLS13,
10272			VerifySignatureAlgorithms: []signatureAlgorithm{
10273				signatureECDSAWithP521AndSHA512,
10274				signatureRSAPKCS1WithSHA384,
10275				signatureRSAPSSWithSHA384,
10276				signatureECDSAWithSHA1,
10277			},
10278		},
10279		shimCertificate: &rsaCertificate,
10280		expectations: connectionExpectations{
10281			peerSignatureAlgorithm: signatureRSAPSSWithSHA384,
10282		},
10283	})
10284
10285	testCases = append(testCases, testCase{
10286		testType: serverTest,
10287		name:     "ServerAuth-SignatureType",
10288		config: Config{
10289			MaxVersion:   VersionTLS12,
10290			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
10291			VerifySignatureAlgorithms: []signatureAlgorithm{
10292				signatureECDSAWithP521AndSHA512,
10293				signatureRSAPKCS1WithSHA384,
10294				signatureECDSAWithSHA1,
10295			},
10296		},
10297		expectations: connectionExpectations{
10298			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA384,
10299		},
10300	})
10301
10302	testCases = append(testCases, testCase{
10303		testType: serverTest,
10304		name:     "ServerAuth-SignatureType-TLS13",
10305		config: Config{
10306			MaxVersion: VersionTLS13,
10307			VerifySignatureAlgorithms: []signatureAlgorithm{
10308				signatureECDSAWithP521AndSHA512,
10309				signatureRSAPKCS1WithSHA384,
10310				signatureRSAPSSWithSHA384,
10311				signatureECDSAWithSHA1,
10312			},
10313		},
10314		expectations: connectionExpectations{
10315			peerSignatureAlgorithm: signatureRSAPSSWithSHA384,
10316		},
10317	})
10318
10319	// Test that signature verification takes the key type into account.
10320	testCases = append(testCases, testCase{
10321		testType: serverTest,
10322		name:     "Verify-ClientAuth-SignatureType",
10323		config: Config{
10324			MaxVersion: VersionTLS12,
10325			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithSHA256),
10326			Bugs: ProtocolBugs{
10327				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
10328			},
10329		},
10330		flags: []string{
10331			"-require-any-client-certificate",
10332		},
10333		shouldFail:    true,
10334		expectedError: ":WRONG_SIGNATURE_TYPE:",
10335	})
10336
10337	testCases = append(testCases, testCase{
10338		testType: serverTest,
10339		name:     "Verify-ClientAuth-SignatureType-TLS13",
10340		config: Config{
10341			MaxVersion: VersionTLS13,
10342			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
10343			Bugs: ProtocolBugs{
10344				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
10345			},
10346		},
10347		flags: []string{
10348			"-require-any-client-certificate",
10349		},
10350		shouldFail:    true,
10351		expectedError: ":WRONG_SIGNATURE_TYPE:",
10352	})
10353
10354	testCases = append(testCases, testCase{
10355		name: "Verify-ServerAuth-SignatureType",
10356		config: Config{
10357			MaxVersion:   VersionTLS12,
10358			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
10359			Credential:   rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithSHA256),
10360			Bugs: ProtocolBugs{
10361				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
10362			},
10363		},
10364		shouldFail:    true,
10365		expectedError: ":WRONG_SIGNATURE_TYPE:",
10366	})
10367
10368	testCases = append(testCases, testCase{
10369		name: "Verify-ServerAuth-SignatureType-TLS13",
10370		config: Config{
10371			MaxVersion: VersionTLS13,
10372			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
10373			Bugs: ProtocolBugs{
10374				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
10375			},
10376		},
10377		shouldFail:    true,
10378		expectedError: ":WRONG_SIGNATURE_TYPE:",
10379	})
10380
10381	// Test that, if the ClientHello list is missing, the server falls back
10382	// to SHA-1 in TLS 1.2, but not TLS 1.3.
10383	testCases = append(testCases, testCase{
10384		testType: serverTest,
10385		name:     "ServerAuth-SHA1-Fallback-RSA",
10386		config: Config{
10387			MaxVersion: VersionTLS12,
10388			VerifySignatureAlgorithms: []signatureAlgorithm{
10389				signatureRSAPKCS1WithSHA1,
10390			},
10391			Bugs: ProtocolBugs{
10392				NoSignatureAlgorithms: true,
10393			},
10394		},
10395		shimCertificate: &rsaCertificate,
10396	})
10397
10398	testCases = append(testCases, testCase{
10399		testType: serverTest,
10400		name:     "ServerAuth-SHA1-Fallback-ECDSA",
10401		config: Config{
10402			MaxVersion: VersionTLS12,
10403			VerifySignatureAlgorithms: []signatureAlgorithm{
10404				signatureECDSAWithSHA1,
10405			},
10406			Bugs: ProtocolBugs{
10407				NoSignatureAlgorithms: true,
10408			},
10409		},
10410		shimCertificate: &ecdsaP256Certificate,
10411	})
10412
10413	testCases = append(testCases, testCase{
10414		testType: serverTest,
10415		name:     "ServerAuth-NoFallback-TLS13",
10416		config: Config{
10417			MaxVersion: VersionTLS13,
10418			VerifySignatureAlgorithms: []signatureAlgorithm{
10419				signatureRSAPKCS1WithSHA1,
10420			},
10421			Bugs: ProtocolBugs{
10422				NoSignatureAlgorithms: true,
10423			},
10424		},
10425		shouldFail:    true,
10426		expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
10427	})
10428
10429	// The CertificateRequest list, however, may never be omitted. It is a
10430	// syntax error for it to be empty.
10431	testCases = append(testCases, testCase{
10432		name: "ClientAuth-NoFallback-RSA",
10433		config: Config{
10434			MaxVersion: VersionTLS12,
10435			ClientAuth: RequireAnyClientCert,
10436			VerifySignatureAlgorithms: []signatureAlgorithm{
10437				signatureRSAPKCS1WithSHA1,
10438			},
10439			Bugs: ProtocolBugs{
10440				NoSignatureAlgorithms: true,
10441			},
10442		},
10443		shimCertificate:    &rsaCertificate,
10444		shouldFail:         true,
10445		expectedError:      ":DECODE_ERROR:",
10446		expectedLocalError: "remote error: error decoding message",
10447	})
10448
10449	testCases = append(testCases, testCase{
10450		name: "ClientAuth-NoFallback-ECDSA",
10451		config: Config{
10452			MaxVersion: VersionTLS12,
10453			ClientAuth: RequireAnyClientCert,
10454			VerifySignatureAlgorithms: []signatureAlgorithm{
10455				signatureECDSAWithSHA1,
10456			},
10457			Bugs: ProtocolBugs{
10458				NoSignatureAlgorithms: true,
10459			},
10460		},
10461		shimCertificate:    &ecdsaP256Certificate,
10462		shouldFail:         true,
10463		expectedError:      ":DECODE_ERROR:",
10464		expectedLocalError: "remote error: error decoding message",
10465	})
10466
10467	testCases = append(testCases, testCase{
10468		name: "ClientAuth-NoFallback-TLS13",
10469		config: Config{
10470			MaxVersion: VersionTLS13,
10471			ClientAuth: RequireAnyClientCert,
10472			VerifySignatureAlgorithms: []signatureAlgorithm{
10473				signatureRSAPKCS1WithSHA1,
10474			},
10475			Bugs: ProtocolBugs{
10476				NoSignatureAlgorithms: true,
10477			},
10478		},
10479		shimCertificate:    &rsaCertificate,
10480		shouldFail:         true,
10481		expectedError:      ":DECODE_ERROR:",
10482		expectedLocalError: "remote error: error decoding message",
10483	})
10484
10485	// Test that signature preferences are enforced. BoringSSL does not
10486	// implement MD5 signatures.
10487	testCases = append(testCases, testCase{
10488		testType: serverTest,
10489		name:     "ClientAuth-Enforced",
10490		config: Config{
10491			MaxVersion: VersionTLS12,
10492			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithMD5),
10493			Bugs: ProtocolBugs{
10494				IgnorePeerSignatureAlgorithmPreferences: true,
10495			},
10496		},
10497		flags:         []string{"-require-any-client-certificate"},
10498		shouldFail:    true,
10499		expectedError: ":WRONG_SIGNATURE_TYPE:",
10500	})
10501
10502	testCases = append(testCases, testCase{
10503		name: "ServerAuth-Enforced",
10504		config: Config{
10505			MaxVersion:   VersionTLS12,
10506			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
10507			Credential:   rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithMD5),
10508			Bugs: ProtocolBugs{
10509				IgnorePeerSignatureAlgorithmPreferences: true,
10510			},
10511		},
10512		shouldFail:    true,
10513		expectedError: ":WRONG_SIGNATURE_TYPE:",
10514	})
10515	testCases = append(testCases, testCase{
10516		testType: serverTest,
10517		name:     "ClientAuth-Enforced-TLS13",
10518		config: Config{
10519			MaxVersion: VersionTLS13,
10520			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithMD5),
10521			Bugs: ProtocolBugs{
10522				IgnorePeerSignatureAlgorithmPreferences: true,
10523				IgnoreSignatureVersionChecks:            true,
10524			},
10525		},
10526		flags:         []string{"-require-any-client-certificate"},
10527		shouldFail:    true,
10528		expectedError: ":WRONG_SIGNATURE_TYPE:",
10529	})
10530
10531	testCases = append(testCases, testCase{
10532		name: "ServerAuth-Enforced-TLS13",
10533		config: Config{
10534			MaxVersion: VersionTLS13,
10535			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithMD5),
10536			Bugs: ProtocolBugs{
10537				IgnorePeerSignatureAlgorithmPreferences: true,
10538				IgnoreSignatureVersionChecks:            true,
10539			},
10540		},
10541		shouldFail:    true,
10542		expectedError: ":WRONG_SIGNATURE_TYPE:",
10543	})
10544
10545	// Test that the negotiated signature algorithm respects the client and
10546	// server preferences.
10547	testCases = append(testCases, testCase{
10548		name: "NoCommonAlgorithms",
10549		config: Config{
10550			MaxVersion: VersionTLS12,
10551			ClientAuth: RequireAnyClientCert,
10552			VerifySignatureAlgorithms: []signatureAlgorithm{
10553				signatureRSAPKCS1WithSHA512,
10554				signatureRSAPKCS1WithSHA1,
10555			},
10556		},
10557		shimCertificate: rsaCertificate.WithSignatureAlgorithms(signatureRSAPKCS1WithSHA256),
10558		shouldFail:      true,
10559		expectedError:   ":NO_COMMON_SIGNATURE_ALGORITHMS:",
10560	})
10561	testCases = append(testCases, testCase{
10562		name: "NoCommonAlgorithms-TLS13",
10563		config: Config{
10564			MaxVersion: VersionTLS13,
10565			ClientAuth: RequireAnyClientCert,
10566			VerifySignatureAlgorithms: []signatureAlgorithm{
10567				signatureRSAPSSWithSHA512,
10568				signatureRSAPSSWithSHA384,
10569			},
10570		},
10571		shimCertificate: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
10572		shouldFail:      true,
10573		expectedError:   ":NO_COMMON_SIGNATURE_ALGORITHMS:",
10574	})
10575	testCases = append(testCases, testCase{
10576		name: "Agree-Digest-SHA256",
10577		config: Config{
10578			MaxVersion: VersionTLS12,
10579			ClientAuth: RequireAnyClientCert,
10580			VerifySignatureAlgorithms: []signatureAlgorithm{
10581				signatureRSAPKCS1WithSHA1,
10582				signatureRSAPKCS1WithSHA256,
10583			},
10584		},
10585		shimCertificate: rsaCertificate.WithSignatureAlgorithms(
10586			signatureRSAPKCS1WithSHA256,
10587			signatureRSAPKCS1WithSHA1,
10588		),
10589		expectations: connectionExpectations{
10590			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA256,
10591		},
10592	})
10593	testCases = append(testCases, testCase{
10594		name: "Agree-Digest-SHA1",
10595		config: Config{
10596			MaxVersion: VersionTLS12,
10597			ClientAuth: RequireAnyClientCert,
10598			VerifySignatureAlgorithms: []signatureAlgorithm{
10599				signatureRSAPKCS1WithSHA1,
10600			},
10601		},
10602		shimCertificate: rsaCertificate.WithSignatureAlgorithms(
10603			signatureRSAPKCS1WithSHA512,
10604			signatureRSAPKCS1WithSHA256,
10605			signatureRSAPKCS1WithSHA1,
10606		),
10607		expectations: connectionExpectations{
10608			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA1,
10609		},
10610	})
10611	testCases = append(testCases, testCase{
10612		name: "Agree-Digest-Default",
10613		config: Config{
10614			MaxVersion: VersionTLS12,
10615			ClientAuth: RequireAnyClientCert,
10616			VerifySignatureAlgorithms: []signatureAlgorithm{
10617				signatureRSAPKCS1WithSHA256,
10618				signatureECDSAWithP256AndSHA256,
10619				signatureRSAPKCS1WithSHA1,
10620				signatureECDSAWithSHA1,
10621			},
10622		},
10623		shimCertificate: &rsaCertificate,
10624		expectations: connectionExpectations{
10625			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA256,
10626		},
10627	})
10628
10629	// Test that the signing preference list may include extra algorithms
10630	// without negotiation problems.
10631	testCases = append(testCases, testCase{
10632		testType: serverTest,
10633		name:     "FilterExtraAlgorithms",
10634		config: Config{
10635			MaxVersion: VersionTLS12,
10636			VerifySignatureAlgorithms: []signatureAlgorithm{
10637				signatureRSAPKCS1WithSHA256,
10638			},
10639		},
10640		shimCertificate: rsaCertificate.WithSignatureAlgorithms(
10641			signatureECDSAWithP256AndSHA256,
10642			signatureRSAPKCS1WithSHA256,
10643		),
10644		expectations: connectionExpectations{
10645			peerSignatureAlgorithm: signatureRSAPKCS1WithSHA256,
10646		},
10647	})
10648
10649	// In TLS 1.2 and below, ECDSA uses the curve list rather than the
10650	// signature algorithms.
10651	testCases = append(testCases, testCase{
10652		name: "CheckLeafCurve",
10653		config: Config{
10654			MaxVersion:   VersionTLS12,
10655			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
10656			Credential:   &ecdsaP256Certificate,
10657		},
10658		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
10659		shouldFail:    true,
10660		expectedError: ":BAD_ECC_CERT:",
10661	})
10662
10663	// In TLS 1.3, ECDSA does not use the ECDHE curve list.
10664	testCases = append(testCases, testCase{
10665		name: "CheckLeafCurve-TLS13",
10666		config: Config{
10667			MaxVersion: VersionTLS13,
10668			Credential: &ecdsaP256Certificate,
10669		},
10670		flags: []string{"-curves", strconv.Itoa(int(CurveP384))},
10671	})
10672
10673	// In TLS 1.2, the ECDSA curve is not in the signature algorithm, so the
10674	// shim should accept P-256 with SHA-384.
10675	testCases = append(testCases, testCase{
10676		name: "ECDSACurveMismatch-Verify-TLS12",
10677		config: Config{
10678			MaxVersion:   VersionTLS12,
10679			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
10680			Credential:   ecdsaP256Certificate.WithSignatureAlgorithms(signatureECDSAWithP384AndSHA384),
10681		},
10682	})
10683
10684	// In TLS 1.3, the ECDSA curve comes from the signature algorithm, so the
10685	// shim should reject P-256 with SHA-384.
10686	testCases = append(testCases, testCase{
10687		name: "ECDSACurveMismatch-Verify-TLS13",
10688		config: Config{
10689			MaxVersion: VersionTLS13,
10690			Credential: ecdsaP256Certificate.WithSignatureAlgorithms(signatureECDSAWithP384AndSHA384),
10691			Bugs: ProtocolBugs{
10692				SkipECDSACurveCheck: true,
10693			},
10694		},
10695		shouldFail:    true,
10696		expectedError: ":WRONG_SIGNATURE_TYPE:",
10697	})
10698
10699	// Signature algorithm selection in TLS 1.3 should take the curve into
10700	// account.
10701	testCases = append(testCases, testCase{
10702		testType: serverTest,
10703		name:     "ECDSACurveMismatch-Sign-TLS13",
10704		config: Config{
10705			MaxVersion: VersionTLS13,
10706			VerifySignatureAlgorithms: []signatureAlgorithm{
10707				signatureECDSAWithP384AndSHA384,
10708				signatureECDSAWithP256AndSHA256,
10709			},
10710		},
10711		shimCertificate: &ecdsaP256Certificate,
10712		expectations: connectionExpectations{
10713			peerSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
10714		},
10715	})
10716
10717	// RSASSA-PSS with SHA-512 is too large for 1024-bit RSA. Test that the
10718	// server does not attempt to sign in that case.
10719	testCases = append(testCases, testCase{
10720		testType: serverTest,
10721		name:     "RSA-PSS-Large",
10722		config: Config{
10723			MaxVersion: VersionTLS13,
10724			VerifySignatureAlgorithms: []signatureAlgorithm{
10725				signatureRSAPSSWithSHA512,
10726			},
10727		},
10728		shimCertificate: &rsa1024Certificate,
10729		shouldFail:      true,
10730		expectedError:   ":NO_COMMON_SIGNATURE_ALGORITHMS:",
10731	})
10732
10733	// Test that RSA-PSS is enabled by default for TLS 1.2.
10734	testCases = append(testCases, testCase{
10735		testType: clientTest,
10736		name:     "RSA-PSS-Default-Verify",
10737		config: Config{
10738			MaxVersion: VersionTLS12,
10739			Credential: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
10740		},
10741		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
10742	})
10743
10744	testCases = append(testCases, testCase{
10745		testType: serverTest,
10746		name:     "RSA-PSS-Default-Sign",
10747		config: Config{
10748			MaxVersion: VersionTLS12,
10749			VerifySignatureAlgorithms: []signatureAlgorithm{
10750				signatureRSAPSSWithSHA256,
10751			},
10752		},
10753		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
10754	})
10755
10756	// TLS 1.1 and below has no way to advertise support for or negotiate
10757	// Ed25519's signature algorithm.
10758	testCases = append(testCases, testCase{
10759		testType: clientTest,
10760		name:     "NoEd25519-TLS11-ServerAuth-Verify",
10761		config: Config{
10762			MaxVersion: VersionTLS11,
10763			Credential: &ed25519Certificate,
10764			Bugs: ProtocolBugs{
10765				// Sign with Ed25519 even though it is TLS 1.1.
10766				SigningAlgorithmForLegacyVersions: signatureEd25519,
10767			},
10768		},
10769		flags:         []string{"-verify-prefs", strconv.Itoa(int(signatureEd25519))},
10770		shouldFail:    true,
10771		expectedError: ":PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE:",
10772	})
10773	testCases = append(testCases, testCase{
10774		testType: serverTest,
10775		name:     "NoEd25519-TLS11-ServerAuth-Sign",
10776		config: Config{
10777			MaxVersion: VersionTLS11,
10778		},
10779		shimCertificate: &ed25519Certificate,
10780		shouldFail:      true,
10781		expectedError:   ":NO_SHARED_CIPHER:",
10782	})
10783	testCases = append(testCases, testCase{
10784		testType: serverTest,
10785		name:     "NoEd25519-TLS11-ClientAuth-Verify",
10786		config: Config{
10787			MaxVersion: VersionTLS11,
10788			Credential: &ed25519Certificate,
10789			Bugs: ProtocolBugs{
10790				// Sign with Ed25519 even though it is TLS 1.1.
10791				SigningAlgorithmForLegacyVersions: signatureEd25519,
10792			},
10793		},
10794		flags: []string{
10795			"-verify-prefs", strconv.Itoa(int(signatureEd25519)),
10796			"-require-any-client-certificate",
10797		},
10798		shouldFail:    true,
10799		expectedError: ":PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE:",
10800	})
10801	testCases = append(testCases, testCase{
10802		testType: clientTest,
10803		name:     "NoEd25519-TLS11-ClientAuth-Sign",
10804		config: Config{
10805			MaxVersion: VersionTLS11,
10806			ClientAuth: RequireAnyClientCert,
10807		},
10808		shimCertificate: &ed25519Certificate,
10809		shouldFail:      true,
10810		expectedError:   ":NO_COMMON_SIGNATURE_ALGORITHMS:",
10811	})
10812
10813	// Test Ed25519 is not advertised by default.
10814	testCases = append(testCases, testCase{
10815		testType: clientTest,
10816		name:     "Ed25519DefaultDisable-NoAdvertise",
10817		config: Config{
10818			Credential: &ed25519Certificate,
10819		},
10820		shouldFail:         true,
10821		expectedLocalError: "tls: no common signature algorithms",
10822	})
10823
10824	// Test Ed25519, when disabled, is not accepted if the peer ignores our
10825	// preferences.
10826	testCases = append(testCases, testCase{
10827		testType: clientTest,
10828		name:     "Ed25519DefaultDisable-NoAccept",
10829		config: Config{
10830			Credential: &ed25519Certificate,
10831			Bugs: ProtocolBugs{
10832				IgnorePeerSignatureAlgorithmPreferences: true,
10833			},
10834		},
10835		shouldFail:         true,
10836		expectedLocalError: "remote error: illegal parameter",
10837		expectedError:      ":WRONG_SIGNATURE_TYPE:",
10838	})
10839
10840	// Test that configuring verify preferences changes what the client
10841	// advertises.
10842	testCases = append(testCases, testCase{
10843		name: "VerifyPreferences-Advertised",
10844		config: Config{
10845			Credential: rsaCertificate.WithSignatureAlgorithms(
10846				signatureRSAPSSWithSHA256,
10847				signatureRSAPSSWithSHA384,
10848				signatureRSAPSSWithSHA512,
10849			),
10850		},
10851		flags: []string{
10852			"-verify-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
10853			"-expect-peer-signature-algorithm", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
10854		},
10855	})
10856
10857	// Test that the client advertises a set which the runner can find
10858	// nothing in common with.
10859	testCases = append(testCases, testCase{
10860		name: "VerifyPreferences-NoCommonAlgorithms",
10861		config: Config{
10862			Credential: rsaCertificate.WithSignatureAlgorithms(
10863				signatureRSAPSSWithSHA256,
10864				signatureRSAPSSWithSHA512,
10865			),
10866		},
10867		flags: []string{
10868			"-verify-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
10869		},
10870		shouldFail:         true,
10871		expectedLocalError: "tls: no common signature algorithms",
10872	})
10873
10874	// Test that the client enforces its preferences when configured.
10875	testCases = append(testCases, testCase{
10876		name: "VerifyPreferences-Enforced",
10877		config: Config{
10878			Credential: rsaCertificate.WithSignatureAlgorithms(
10879				signatureRSAPSSWithSHA256,
10880				signatureRSAPSSWithSHA512,
10881			),
10882			Bugs: ProtocolBugs{
10883				IgnorePeerSignatureAlgorithmPreferences: true,
10884			},
10885		},
10886		flags: []string{
10887			"-verify-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA384)),
10888		},
10889		shouldFail:         true,
10890		expectedLocalError: "remote error: illegal parameter",
10891		expectedError:      ":WRONG_SIGNATURE_TYPE:",
10892	})
10893
10894	// Test that explicitly configuring Ed25519 is as good as changing the
10895	// boolean toggle.
10896	testCases = append(testCases, testCase{
10897		name: "VerifyPreferences-Ed25519",
10898		config: Config{
10899			Credential: &ed25519Certificate,
10900		},
10901		flags: []string{
10902			"-verify-prefs", strconv.Itoa(int(signatureEd25519)),
10903		},
10904	})
10905
10906	for _, testType := range []testType{clientTest, serverTest} {
10907		for _, ver := range tlsVersions {
10908			if ver.version < VersionTLS12 {
10909				continue
10910			}
10911
10912			prefix := "Client-" + ver.name + "-"
10913			noCommonAlgorithmsError := ":NO_COMMON_SIGNATURE_ALGORITHMS:"
10914			if testType == serverTest {
10915				prefix = "Server-" + ver.name + "-"
10916				// In TLS 1.2 servers, cipher selection and algorithm
10917				// selection are linked.
10918				if ver.version <= VersionTLS12 {
10919					noCommonAlgorithmsError = ":NO_SHARED_CIPHER:"
10920				}
10921			}
10922
10923			// Test that the shim will not sign MD5/SHA1 with RSA at TLS 1.2,
10924			// even if specified in signing preferences.
10925			testCases = append(testCases, testCase{
10926				testType: testType,
10927				name:     prefix + "NoSign-RSA_PKCS1_MD5_SHA1",
10928				config: Config{
10929					MaxVersion:                ver.version,
10930					CipherSuites:              signingCiphers,
10931					ClientAuth:                RequireAnyClientCert,
10932					VerifySignatureAlgorithms: []signatureAlgorithm{signatureRSAPKCS1WithMD5AndSHA1},
10933				},
10934				shimCertificate: rsaCertificate.WithSignatureAlgorithms(
10935					signatureRSAPKCS1WithMD5AndSHA1,
10936					// Include a valid algorithm as well, to avoid an empty list
10937					// if filtered out.
10938					signatureRSAPKCS1WithSHA256,
10939				),
10940				shouldFail:    true,
10941				expectedError: noCommonAlgorithmsError,
10942			})
10943
10944			// Test that the shim will not accept MD5/SHA1 with RSA at TLS 1.2,
10945			// even if specified in verify preferences.
10946			testCases = append(testCases, testCase{
10947				testType: testType,
10948				name:     prefix + "NoVerify-RSA_PKCS1_MD5_SHA1",
10949				config: Config{
10950					MaxVersion: ver.version,
10951					Credential: &rsaCertificate,
10952					Bugs: ProtocolBugs{
10953						IgnorePeerSignatureAlgorithmPreferences: true,
10954						AlwaysSignAsLegacyVersion:               true,
10955						SendSignatureAlgorithm:                  signatureRSAPKCS1WithMD5AndSHA1,
10956					},
10957				},
10958				shimCertificate: &rsaCertificate,
10959				flags: []string{
10960					"-verify-prefs", strconv.Itoa(int(signatureRSAPKCS1WithMD5AndSHA1)),
10961					// Include a valid algorithm as well, to avoid an empty list
10962					// if filtered out.
10963					"-verify-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA256)),
10964					"-require-any-client-certificate",
10965				},
10966				shouldFail:    true,
10967				expectedError: ":WRONG_SIGNATURE_TYPE:",
10968			})
10969		}
10970	}
10971
10972	// Test that, when there are no signature algorithms in common in TLS
10973	// 1.2, the server will still consider the legacy RSA key exchange.
10974	testCases = append(testCases, testCase{
10975		testType: serverTest,
10976		name:     "NoCommonSignatureAlgorithms-TLS12-Fallback",
10977		config: Config{
10978			MaxVersion: VersionTLS12,
10979			CipherSuites: []uint16{
10980				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
10981				TLS_RSA_WITH_AES_128_GCM_SHA256,
10982			},
10983			VerifySignatureAlgorithms: []signatureAlgorithm{
10984				signatureECDSAWithP256AndSHA256,
10985			},
10986		},
10987		expectations: connectionExpectations{
10988			cipher: TLS_RSA_WITH_AES_128_GCM_SHA256,
10989		},
10990	})
10991}
10992
10993// timeouts is the retransmit schedule for BoringSSL. It doubles and
10994// caps at 60 seconds. On the 13th timeout, it gives up.
10995var timeouts = []time.Duration{
10996	1 * time.Second,
10997	2 * time.Second,
10998	4 * time.Second,
10999	8 * time.Second,
11000	16 * time.Second,
11001	32 * time.Second,
11002	60 * time.Second,
11003	60 * time.Second,
11004	60 * time.Second,
11005	60 * time.Second,
11006	60 * time.Second,
11007	60 * time.Second,
11008	60 * time.Second,
11009}
11010
11011// shortTimeouts is an alternate set of timeouts which would occur if the
11012// initial timeout duration was set to 250ms.
11013var shortTimeouts = []time.Duration{
11014	250 * time.Millisecond,
11015	500 * time.Millisecond,
11016	1 * time.Second,
11017	2 * time.Second,
11018	4 * time.Second,
11019	8 * time.Second,
11020	16 * time.Second,
11021	32 * time.Second,
11022	60 * time.Second,
11023	60 * time.Second,
11024	60 * time.Second,
11025	60 * time.Second,
11026	60 * time.Second,
11027}
11028
11029func addDTLSRetransmitTests() {
11030	// These tests work by coordinating some behavior on both the shim and
11031	// the runner.
11032	//
11033	// TimeoutSchedule configures the runner to send a series of timeout
11034	// opcodes to the shim (see packetAdaptor) immediately before reading
11035	// each peer handshake flight N. The timeout opcode both simulates a
11036	// timeout in the shim and acts as a synchronization point to help the
11037	// runner bracket each handshake flight.
11038	//
11039	// We assume the shim does not read from the channel eagerly. It must
11040	// first wait until it has sent flight N and is ready to receive
11041	// handshake flight N+1. At this point, it will process the timeout
11042	// opcode. It must then immediately respond with a timeout ACK and act
11043	// as if the shim was idle for the specified amount of time.
11044	//
11045	// The runner then drops all packets received before the ACK and
11046	// continues waiting for flight N. This ordering results in one attempt
11047	// at sending flight N to be dropped. For the test to complete, the
11048	// shim must send flight N again, testing that the shim implements DTLS
11049	// retransmit on a timeout.
11050
11051	// TODO(davidben): Add DTLS 1.3 versions of these tests. There will
11052	// likely be more epochs to cross and the final message's retransmit may
11053	// be more complex.
11054
11055	// Test that this is indeed the timeout schedule. Stress all
11056	// four patterns of handshake.
11057	for i := 1; i < len(timeouts); i++ {
11058		number := strconv.Itoa(i)
11059		testCases = append(testCases, testCase{
11060			protocol: dtls,
11061			name:     "DTLS-Retransmit-Client-" + number,
11062			config: Config{
11063				MaxVersion: VersionTLS12,
11064				Bugs: ProtocolBugs{
11065					TimeoutSchedule: timeouts[:i],
11066				},
11067			},
11068			resumeSession: true,
11069			flags:         []string{"-async"},
11070		})
11071		testCases = append(testCases, testCase{
11072			protocol: dtls,
11073			testType: serverTest,
11074			name:     "DTLS-Retransmit-Server-" + number,
11075			config: Config{
11076				MaxVersion: VersionTLS12,
11077				Bugs: ProtocolBugs{
11078					TimeoutSchedule: timeouts[:i],
11079				},
11080			},
11081			resumeSession: true,
11082			flags:         []string{"-async"},
11083		})
11084	}
11085
11086	// Test that exceeding the timeout schedule hits a read
11087	// timeout.
11088	testCases = append(testCases, testCase{
11089		protocol: dtls,
11090		name:     "DTLS-Retransmit-Timeout",
11091		config: Config{
11092			MaxVersion: VersionTLS12,
11093			Bugs: ProtocolBugs{
11094				TimeoutSchedule: timeouts,
11095			},
11096		},
11097		resumeSession: true,
11098		flags:         []string{"-async"},
11099		shouldFail:    true,
11100		expectedError: ":READ_TIMEOUT_EXPIRED:",
11101	})
11102
11103	// Test that timeout handling has a fudge factor, due to API
11104	// problems.
11105	testCases = append(testCases, testCase{
11106		protocol: dtls,
11107		name:     "DTLS-Retransmit-Fudge",
11108		config: Config{
11109			MaxVersion: VersionTLS12,
11110			Bugs: ProtocolBugs{
11111				TimeoutSchedule: []time.Duration{
11112					timeouts[0] - 10*time.Millisecond,
11113				},
11114			},
11115		},
11116		resumeSession: true,
11117		flags:         []string{"-async"},
11118	})
11119
11120	// Test that the final Finished retransmitting isn't
11121	// duplicated if the peer badly fragments everything.
11122	testCases = append(testCases, testCase{
11123		testType: serverTest,
11124		protocol: dtls,
11125		name:     "DTLS-Retransmit-Fragmented",
11126		config: Config{
11127			MaxVersion: VersionTLS12,
11128			Bugs: ProtocolBugs{
11129				TimeoutSchedule:          []time.Duration{timeouts[0]},
11130				MaxHandshakeRecordLength: 2,
11131			},
11132		},
11133		flags: []string{"-async"},
11134	})
11135
11136	// Test the timeout schedule when a shorter initial timeout duration is set.
11137	testCases = append(testCases, testCase{
11138		protocol: dtls,
11139		name:     "DTLS-Retransmit-Short-Client",
11140		config: Config{
11141			MaxVersion: VersionTLS12,
11142			Bugs: ProtocolBugs{
11143				TimeoutSchedule: shortTimeouts[:len(shortTimeouts)-1],
11144			},
11145		},
11146		resumeSession: true,
11147		flags: []string{
11148			"-async",
11149			"-initial-timeout-duration-ms", "250",
11150		},
11151	})
11152	testCases = append(testCases, testCase{
11153		protocol: dtls,
11154		testType: serverTest,
11155		name:     "DTLS-Retransmit-Short-Server",
11156		config: Config{
11157			MaxVersion: VersionTLS12,
11158			Bugs: ProtocolBugs{
11159				TimeoutSchedule: shortTimeouts[:len(shortTimeouts)-1],
11160			},
11161		},
11162		resumeSession: true,
11163		flags: []string{
11164			"-async",
11165			"-initial-timeout-duration-ms", "250",
11166		},
11167	})
11168
11169	// If the shim sends the last Finished (server full or client resume
11170	// handshakes), it must retransmit that Finished when it sees a
11171	// post-handshake penultimate Finished from the runner. The above tests
11172	// cover this. Conversely, if the shim sends the penultimate Finished
11173	// (client full or server resume), test that it does not retransmit.
11174	testCases = append(testCases, testCase{
11175		protocol: dtls,
11176		testType: clientTest,
11177		name:     "DTLS-StrayRetransmitFinished-ClientFull",
11178		config: Config{
11179			MaxVersion: VersionTLS12,
11180			Bugs: ProtocolBugs{
11181				RetransmitFinished: true,
11182			},
11183		},
11184	})
11185	testCases = append(testCases, testCase{
11186		protocol: dtls,
11187		testType: serverTest,
11188		name:     "DTLS-StrayRetransmitFinished-ServerResume",
11189		config: Config{
11190			MaxVersion: VersionTLS12,
11191		},
11192		resumeConfig: &Config{
11193			MaxVersion: VersionTLS12,
11194			Bugs: ProtocolBugs{
11195				RetransmitFinished: true,
11196			},
11197		},
11198		resumeSession: true,
11199	})
11200}
11201
11202func addExportKeyingMaterialTests() {
11203	for _, vers := range tlsVersions {
11204		testCases = append(testCases, testCase{
11205			name: "ExportKeyingMaterial-" + vers.name,
11206			config: Config{
11207				MaxVersion: vers.version,
11208			},
11209			// Test the exporter in both initial and resumption
11210			// handshakes.
11211			resumeSession:        true,
11212			exportKeyingMaterial: 1024,
11213			exportLabel:          "label",
11214			exportContext:        "context",
11215			useExportContext:     true,
11216		})
11217		testCases = append(testCases, testCase{
11218			name: "ExportKeyingMaterial-NoContext-" + vers.name,
11219			config: Config{
11220				MaxVersion: vers.version,
11221			},
11222			exportKeyingMaterial: 1024,
11223		})
11224		testCases = append(testCases, testCase{
11225			name: "ExportKeyingMaterial-EmptyContext-" + vers.name,
11226			config: Config{
11227				MaxVersion: vers.version,
11228			},
11229			exportKeyingMaterial: 1024,
11230			useExportContext:     true,
11231		})
11232		testCases = append(testCases, testCase{
11233			name: "ExportKeyingMaterial-Small-" + vers.name,
11234			config: Config{
11235				MaxVersion: vers.version,
11236			},
11237			exportKeyingMaterial: 1,
11238			exportLabel:          "label",
11239			exportContext:        "context",
11240			useExportContext:     true,
11241		})
11242
11243		if vers.version >= VersionTLS13 {
11244			// Test the exporters do not work while the client is
11245			// sending 0-RTT data.
11246			testCases = append(testCases, testCase{
11247				name: "NoEarlyKeyingMaterial-Client-InEarlyData-" + vers.name,
11248				config: Config{
11249					MaxVersion: vers.version,
11250				},
11251				resumeSession: true,
11252				earlyData:     true,
11253				flags: []string{
11254					"-on-resume-export-keying-material", "1024",
11255					"-on-resume-export-label", "label",
11256					"-on-resume-export-context", "context",
11257				},
11258				shouldFail:    true,
11259				expectedError: ":HANDSHAKE_NOT_COMPLETE:",
11260			})
11261
11262			// Test the normal exporter on the server in half-RTT.
11263			testCases = append(testCases, testCase{
11264				testType: serverTest,
11265				name:     "ExportKeyingMaterial-Server-HalfRTT-" + vers.name,
11266				config: Config{
11267					MaxVersion: vers.version,
11268					Bugs: ProtocolBugs{
11269						// The shim writes exported data immediately after
11270						// the handshake returns, so disable the built-in
11271						// early data test.
11272						SendEarlyData:     [][]byte{},
11273						ExpectHalfRTTData: [][]byte{},
11274					},
11275				},
11276				resumeSession:        true,
11277				earlyData:            true,
11278				exportKeyingMaterial: 1024,
11279				exportLabel:          "label",
11280				exportContext:        "context",
11281				useExportContext:     true,
11282			})
11283		}
11284	}
11285
11286	// Exporters work during a False Start.
11287	testCases = append(testCases, testCase{
11288		name: "ExportKeyingMaterial-FalseStart",
11289		config: Config{
11290			MaxVersion:   VersionTLS12,
11291			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11292			NextProtos:   []string{"foo"},
11293			Bugs: ProtocolBugs{
11294				ExpectFalseStart: true,
11295			},
11296		},
11297		flags: []string{
11298			"-false-start",
11299			"-advertise-alpn", "\x03foo",
11300			"-expect-alpn", "foo",
11301		},
11302		shimWritesFirst:      true,
11303		exportKeyingMaterial: 1024,
11304		exportLabel:          "label",
11305		exportContext:        "context",
11306		useExportContext:     true,
11307	})
11308
11309	// Exporters do not work in the middle of a renegotiation. Test this by
11310	// triggering the exporter after every SSL_read call and configuring the
11311	// shim to run asynchronously.
11312	testCases = append(testCases, testCase{
11313		name: "ExportKeyingMaterial-Renegotiate",
11314		config: Config{
11315			MaxVersion: VersionTLS12,
11316		},
11317		renegotiate: 1,
11318		flags: []string{
11319			"-async",
11320			"-use-exporter-between-reads",
11321			"-renegotiate-freely",
11322			"-expect-total-renegotiations", "1",
11323		},
11324		shouldFail:    true,
11325		expectedError: "failed to export keying material",
11326	})
11327}
11328
11329func addExportTrafficSecretsTests() {
11330	for _, cipherSuite := range []testCipherSuite{
11331		// Test a SHA-256 and SHA-384 based cipher suite.
11332		{"AEAD-AES128-GCM-SHA256", TLS_AES_128_GCM_SHA256},
11333		{"AEAD-AES256-GCM-SHA384", TLS_AES_256_GCM_SHA384},
11334	} {
11335
11336		testCases = append(testCases, testCase{
11337			name: "ExportTrafficSecrets-" + cipherSuite.name,
11338			config: Config{
11339				MinVersion:   VersionTLS13,
11340				CipherSuites: []uint16{cipherSuite.id},
11341			},
11342			exportTrafficSecrets: true,
11343		})
11344	}
11345}
11346
11347func addTLSUniqueTests() {
11348	for _, isClient := range []bool{false, true} {
11349		for _, isResumption := range []bool{false, true} {
11350			for _, hasEMS := range []bool{false, true} {
11351				var suffix string
11352				if isResumption {
11353					suffix = "Resume-"
11354				} else {
11355					suffix = "Full-"
11356				}
11357
11358				if hasEMS {
11359					suffix += "EMS-"
11360				} else {
11361					suffix += "NoEMS-"
11362				}
11363
11364				if isClient {
11365					suffix += "Client"
11366				} else {
11367					suffix += "Server"
11368				}
11369
11370				test := testCase{
11371					name:          "TLSUnique-" + suffix,
11372					testTLSUnique: true,
11373					config: Config{
11374						MaxVersion: VersionTLS12,
11375						Bugs: ProtocolBugs{
11376							NoExtendedMasterSecret: !hasEMS,
11377						},
11378					},
11379				}
11380
11381				if isResumption {
11382					test.resumeSession = true
11383					test.resumeConfig = &Config{
11384						MaxVersion: VersionTLS12,
11385						Bugs: ProtocolBugs{
11386							NoExtendedMasterSecret: !hasEMS,
11387						},
11388					}
11389				}
11390
11391				if isResumption && !hasEMS {
11392					test.shouldFail = true
11393					test.expectedError = "failed to get tls-unique"
11394				}
11395
11396				testCases = append(testCases, test)
11397			}
11398		}
11399	}
11400}
11401
11402func addCustomExtensionTests() {
11403	// Test an unknown extension from the server.
11404	testCases = append(testCases, testCase{
11405		testType: clientTest,
11406		name:     "UnknownExtension-Client",
11407		config: Config{
11408			MaxVersion: VersionTLS12,
11409			Bugs: ProtocolBugs{
11410				CustomExtension: "custom extension",
11411			},
11412		},
11413		shouldFail:         true,
11414		expectedError:      ":UNEXPECTED_EXTENSION:",
11415		expectedLocalError: "remote error: unsupported extension",
11416	})
11417	testCases = append(testCases, testCase{
11418		testType: clientTest,
11419		name:     "UnknownExtension-Client-TLS13",
11420		config: Config{
11421			MaxVersion: VersionTLS13,
11422			Bugs: ProtocolBugs{
11423				CustomExtension: "custom extension",
11424			},
11425		},
11426		shouldFail:         true,
11427		expectedError:      ":UNEXPECTED_EXTENSION:",
11428		expectedLocalError: "remote error: unsupported extension",
11429	})
11430	testCases = append(testCases, testCase{
11431		testType: clientTest,
11432		name:     "UnknownUnencryptedExtension-Client-TLS13",
11433		config: Config{
11434			MaxVersion: VersionTLS13,
11435			Bugs: ProtocolBugs{
11436				CustomUnencryptedExtension: "custom extension",
11437			},
11438		},
11439		shouldFail:    true,
11440		expectedError: ":UNEXPECTED_EXTENSION:",
11441		// The shim must send an alert, but alerts at this point do not
11442		// get successfully decrypted by the runner.
11443		expectedLocalError: "local error: bad record MAC",
11444	})
11445	testCases = append(testCases, testCase{
11446		testType: clientTest,
11447		name:     "UnexpectedUnencryptedExtension-Client-TLS13",
11448		config: Config{
11449			MaxVersion: VersionTLS13,
11450			Bugs: ProtocolBugs{
11451				SendUnencryptedALPN: "foo",
11452			},
11453		},
11454		flags: []string{
11455			"-advertise-alpn", "\x03foo\x03bar",
11456		},
11457		shouldFail:    true,
11458		expectedError: ":UNEXPECTED_EXTENSION:",
11459		// The shim must send an alert, but alerts at this point do not
11460		// get successfully decrypted by the runner.
11461		expectedLocalError: "local error: bad record MAC",
11462	})
11463
11464	// Test a known but unoffered extension from the server.
11465	testCases = append(testCases, testCase{
11466		testType: clientTest,
11467		name:     "UnofferedExtension-Client",
11468		config: Config{
11469			MaxVersion: VersionTLS12,
11470			Bugs: ProtocolBugs{
11471				SendALPN: "alpn",
11472			},
11473		},
11474		shouldFail:         true,
11475		expectedError:      ":UNEXPECTED_EXTENSION:",
11476		expectedLocalError: "remote error: unsupported extension",
11477	})
11478	testCases = append(testCases, testCase{
11479		testType: clientTest,
11480		name:     "UnofferedExtension-Client-TLS13",
11481		config: Config{
11482			MaxVersion: VersionTLS13,
11483			Bugs: ProtocolBugs{
11484				SendALPN: "alpn",
11485			},
11486		},
11487		shouldFail:         true,
11488		expectedError:      ":UNEXPECTED_EXTENSION:",
11489		expectedLocalError: "remote error: unsupported extension",
11490	})
11491}
11492
11493func addRSAClientKeyExchangeTests() {
11494	for bad := RSABadValue(1); bad < NumRSABadValues; bad++ {
11495		testCases = append(testCases, testCase{
11496			testType: serverTest,
11497			name:     fmt.Sprintf("BadRSAClientKeyExchange-%d", bad),
11498			config: Config{
11499				// Ensure the ClientHello version and final
11500				// version are different, to detect if the
11501				// server uses the wrong one.
11502				MaxVersion:   VersionTLS11,
11503				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
11504				Bugs: ProtocolBugs{
11505					BadRSAClientKeyExchange: bad,
11506				},
11507			},
11508			shouldFail:    true,
11509			expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
11510		})
11511	}
11512
11513	// The server must compare whatever was in ClientHello.version for the
11514	// RSA premaster.
11515	testCases = append(testCases, testCase{
11516		testType: serverTest,
11517		name:     "SendClientVersion-RSA",
11518		config: Config{
11519			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
11520			Bugs: ProtocolBugs{
11521				SendClientVersion: 0x1234,
11522			},
11523		},
11524		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
11525	})
11526}
11527
11528var testCurves = []struct {
11529	name string
11530	id   CurveID
11531}{
11532	{"P-224", CurveP224},
11533	{"P-256", CurveP256},
11534	{"P-384", CurveP384},
11535	{"P-521", CurveP521},
11536	{"X25519", CurveX25519},
11537	{"Kyber", CurveX25519Kyber768},
11538}
11539
11540const bogusCurve = 0x1234
11541
11542func isPqGroup(r CurveID) bool {
11543	return r == CurveX25519Kyber768
11544}
11545
11546func addCurveTests() {
11547	for _, curve := range testCurves {
11548		for _, ver := range tlsVersions {
11549			if isPqGroup(curve.id) && ver.version < VersionTLS13 {
11550				continue
11551			}
11552
11553			suffix := curve.name + "-" + ver.name
11554
11555			testCases = append(testCases, testCase{
11556				name: "CurveTest-Client-" + suffix,
11557				config: Config{
11558					MaxVersion: ver.version,
11559					CipherSuites: []uint16{
11560						TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
11561						TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
11562						TLS_AES_256_GCM_SHA384,
11563					},
11564					CurvePreferences: []CurveID{curve.id},
11565				},
11566				flags: append(
11567					[]string{"-expect-curve-id", strconv.Itoa(int(curve.id))},
11568					flagInts("-curves", shimConfig.AllCurves)...,
11569				),
11570				expectations: connectionExpectations{
11571					curveID: curve.id,
11572				},
11573			})
11574			testCases = append(testCases, testCase{
11575				testType: serverTest,
11576				name:     "CurveTest-Server-" + suffix,
11577				config: Config{
11578					MaxVersion: ver.version,
11579					CipherSuites: []uint16{
11580						TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
11581						TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
11582						TLS_AES_256_GCM_SHA384,
11583					},
11584					CurvePreferences: []CurveID{curve.id},
11585				},
11586				flags: append(
11587					[]string{"-expect-curve-id", strconv.Itoa(int(curve.id))},
11588					flagInts("-curves", shimConfig.AllCurves)...,
11589				),
11590				expectations: connectionExpectations{
11591					curveID: curve.id,
11592				},
11593			})
11594
11595			if curve.id != CurveX25519 && !isPqGroup(curve.id) {
11596				testCases = append(testCases, testCase{
11597					name: "CurveTest-Client-Compressed-" + suffix,
11598					config: Config{
11599						MaxVersion: ver.version,
11600						CipherSuites: []uint16{
11601							TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
11602							TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
11603							TLS_AES_256_GCM_SHA384,
11604						},
11605						CurvePreferences: []CurveID{curve.id},
11606						Bugs: ProtocolBugs{
11607							SendCompressedCoordinates: true,
11608						},
11609					},
11610					flags:         flagInts("-curves", shimConfig.AllCurves),
11611					shouldFail:    true,
11612					expectedError: ":BAD_ECPOINT:",
11613				})
11614				testCases = append(testCases, testCase{
11615					testType: serverTest,
11616					name:     "CurveTest-Server-Compressed-" + suffix,
11617					config: Config{
11618						MaxVersion: ver.version,
11619						CipherSuites: []uint16{
11620							TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
11621							TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
11622							TLS_AES_256_GCM_SHA384,
11623						},
11624						CurvePreferences: []CurveID{curve.id},
11625						Bugs: ProtocolBugs{
11626							SendCompressedCoordinates: true,
11627						},
11628					},
11629					flags:         flagInts("-curves", shimConfig.AllCurves),
11630					shouldFail:    true,
11631					expectedError: ":BAD_ECPOINT:",
11632				})
11633			}
11634		}
11635	}
11636
11637	// The server must be tolerant to bogus curves.
11638	testCases = append(testCases, testCase{
11639		testType: serverTest,
11640		name:     "UnknownCurve",
11641		config: Config{
11642			MaxVersion:       VersionTLS12,
11643			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11644			CurvePreferences: []CurveID{bogusCurve, CurveP256},
11645		},
11646	})
11647
11648	// The server must be tolerant to bogus curves.
11649	testCases = append(testCases, testCase{
11650		testType: serverTest,
11651		name:     "UnknownCurve-TLS13",
11652		config: Config{
11653			MaxVersion:       VersionTLS13,
11654			CurvePreferences: []CurveID{bogusCurve, CurveP256},
11655		},
11656	})
11657
11658	// The server must not consider ECDHE ciphers when there are no
11659	// supported curves.
11660	testCases = append(testCases, testCase{
11661		testType: serverTest,
11662		name:     "NoSupportedCurves",
11663		config: Config{
11664			MaxVersion:   VersionTLS12,
11665			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11666			Bugs: ProtocolBugs{
11667				NoSupportedCurves: true,
11668			},
11669		},
11670		shouldFail:    true,
11671		expectedError: ":NO_SHARED_CIPHER:",
11672	})
11673	testCases = append(testCases, testCase{
11674		testType: serverTest,
11675		name:     "NoSupportedCurves-TLS13",
11676		config: Config{
11677			MaxVersion: VersionTLS13,
11678			Bugs: ProtocolBugs{
11679				NoSupportedCurves: true,
11680			},
11681		},
11682		shouldFail:    true,
11683		expectedError: ":NO_SHARED_GROUP:",
11684	})
11685
11686	// The server must fall back to another cipher when there are no
11687	// supported curves.
11688	testCases = append(testCases, testCase{
11689		testType: serverTest,
11690		name:     "NoCommonCurves",
11691		config: Config{
11692			MaxVersion: VersionTLS12,
11693			CipherSuites: []uint16{
11694				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
11695				TLS_RSA_WITH_AES_128_GCM_SHA256,
11696			},
11697			CurvePreferences: []CurveID{CurveP224},
11698		},
11699		expectations: connectionExpectations{
11700			cipher: TLS_RSA_WITH_AES_128_GCM_SHA256,
11701		},
11702	})
11703
11704	// The client must reject bogus curves and disabled curves.
11705	testCases = append(testCases, testCase{
11706		name: "BadECDHECurve",
11707		config: Config{
11708			MaxVersion:   VersionTLS12,
11709			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11710			Bugs: ProtocolBugs{
11711				SendCurve: bogusCurve,
11712			},
11713		},
11714		shouldFail:    true,
11715		expectedError: ":WRONG_CURVE:",
11716	})
11717	testCases = append(testCases, testCase{
11718		name: "BadECDHECurve-TLS13",
11719		config: Config{
11720			MaxVersion: VersionTLS13,
11721			Bugs: ProtocolBugs{
11722				SendCurve: bogusCurve,
11723			},
11724		},
11725		shouldFail:    true,
11726		expectedError: ":WRONG_CURVE:",
11727	})
11728
11729	testCases = append(testCases, testCase{
11730		name: "UnsupportedCurve",
11731		config: Config{
11732			MaxVersion:       VersionTLS12,
11733			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11734			CurvePreferences: []CurveID{CurveP256},
11735			Bugs: ProtocolBugs{
11736				IgnorePeerCurvePreferences: true,
11737			},
11738		},
11739		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
11740		shouldFail:    true,
11741		expectedError: ":WRONG_CURVE:",
11742	})
11743
11744	testCases = append(testCases, testCase{
11745		// TODO(davidben): Add a TLS 1.3 version where
11746		// HelloRetryRequest requests an unsupported curve.
11747		name: "UnsupportedCurve-ServerHello-TLS13",
11748		config: Config{
11749			MaxVersion:       VersionTLS13,
11750			CurvePreferences: []CurveID{CurveP384},
11751			Bugs: ProtocolBugs{
11752				SendCurve: CurveP256,
11753			},
11754		},
11755		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
11756		shouldFail:    true,
11757		expectedError: ":WRONG_CURVE:",
11758	})
11759
11760	// Test invalid curve points.
11761	testCases = append(testCases, testCase{
11762		name: "InvalidECDHPoint-Client",
11763		config: Config{
11764			MaxVersion:       VersionTLS12,
11765			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11766			CurvePreferences: []CurveID{CurveP256},
11767			Bugs: ProtocolBugs{
11768				InvalidECDHPoint: true,
11769			},
11770		},
11771		shouldFail:    true,
11772		expectedError: ":BAD_ECPOINT:",
11773	})
11774	testCases = append(testCases, testCase{
11775		name: "InvalidECDHPoint-Client-TLS13",
11776		config: Config{
11777			MaxVersion:       VersionTLS13,
11778			CurvePreferences: []CurveID{CurveP256},
11779			Bugs: ProtocolBugs{
11780				InvalidECDHPoint: true,
11781			},
11782		},
11783		shouldFail:    true,
11784		expectedError: ":BAD_ECPOINT:",
11785	})
11786	testCases = append(testCases, testCase{
11787		testType: serverTest,
11788		name:     "InvalidECDHPoint-Server",
11789		config: Config{
11790			MaxVersion:       VersionTLS12,
11791			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11792			CurvePreferences: []CurveID{CurveP256},
11793			Bugs: ProtocolBugs{
11794				InvalidECDHPoint: true,
11795			},
11796		},
11797		shouldFail:    true,
11798		expectedError: ":BAD_ECPOINT:",
11799	})
11800	testCases = append(testCases, testCase{
11801		testType: serverTest,
11802		name:     "InvalidECDHPoint-Server-TLS13",
11803		config: Config{
11804			MaxVersion:       VersionTLS13,
11805			CurvePreferences: []CurveID{CurveP256},
11806			Bugs: ProtocolBugs{
11807				InvalidECDHPoint: true,
11808			},
11809		},
11810		shouldFail:    true,
11811		expectedError: ":BAD_ECPOINT:",
11812	})
11813
11814	// The previous curve ID should be reported on TLS 1.2 resumption.
11815	testCases = append(testCases, testCase{
11816		name: "CurveID-Resume-Client",
11817		config: Config{
11818			MaxVersion:       VersionTLS12,
11819			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11820			CurvePreferences: []CurveID{CurveX25519},
11821		},
11822		flags:         []string{"-expect-curve-id", strconv.Itoa(int(CurveX25519))},
11823		resumeSession: true,
11824	})
11825	testCases = append(testCases, testCase{
11826		testType: serverTest,
11827		name:     "CurveID-Resume-Server",
11828		config: Config{
11829			MaxVersion:       VersionTLS12,
11830			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
11831			CurvePreferences: []CurveID{CurveX25519},
11832		},
11833		flags:         []string{"-expect-curve-id", strconv.Itoa(int(CurveX25519))},
11834		resumeSession: true,
11835	})
11836
11837	// TLS 1.3 allows resuming at a differet curve. If this happens, the new
11838	// one should be reported.
11839	testCases = append(testCases, testCase{
11840		name: "CurveID-Resume-Client-TLS13",
11841		config: Config{
11842			MaxVersion:       VersionTLS13,
11843			CurvePreferences: []CurveID{CurveX25519},
11844		},
11845		resumeConfig: &Config{
11846			MaxVersion:       VersionTLS13,
11847			CurvePreferences: []CurveID{CurveP256},
11848		},
11849		flags: []string{
11850			"-on-initial-expect-curve-id", strconv.Itoa(int(CurveX25519)),
11851			"-on-resume-expect-curve-id", strconv.Itoa(int(CurveP256)),
11852		},
11853		resumeSession: true,
11854	})
11855	testCases = append(testCases, testCase{
11856		testType: serverTest,
11857		name:     "CurveID-Resume-Server-TLS13",
11858		config: Config{
11859			MaxVersion:       VersionTLS13,
11860			CurvePreferences: []CurveID{CurveX25519},
11861		},
11862		resumeConfig: &Config{
11863			MaxVersion:       VersionTLS13,
11864			CurvePreferences: []CurveID{CurveP256},
11865		},
11866		flags: []string{
11867			"-on-initial-expect-curve-id", strconv.Itoa(int(CurveX25519)),
11868			"-on-resume-expect-curve-id", strconv.Itoa(int(CurveP256)),
11869		},
11870		resumeSession: true,
11871	})
11872
11873	// Server-sent point formats are legal in TLS 1.2, but not in TLS 1.3.
11874	testCases = append(testCases, testCase{
11875		name: "PointFormat-ServerHello-TLS12",
11876		config: Config{
11877			MaxVersion: VersionTLS12,
11878			Bugs: ProtocolBugs{
11879				SendSupportedPointFormats: []byte{pointFormatUncompressed},
11880			},
11881		},
11882	})
11883	testCases = append(testCases, testCase{
11884		name: "PointFormat-EncryptedExtensions-TLS13",
11885		config: Config{
11886			MaxVersion: VersionTLS13,
11887			Bugs: ProtocolBugs{
11888				SendSupportedPointFormats: []byte{pointFormatUncompressed},
11889			},
11890		},
11891		shouldFail:    true,
11892		expectedError: ":ERROR_PARSING_EXTENSION:",
11893	})
11894
11895	// Server-sent supported groups/curves are legal in TLS 1.3. They are
11896	// illegal in TLS 1.2, but some servers send them anyway, so we must
11897	// tolerate them.
11898	testCases = append(testCases, testCase{
11899		name: "SupportedCurves-ServerHello-TLS12",
11900		config: Config{
11901			MaxVersion: VersionTLS12,
11902			Bugs: ProtocolBugs{
11903				SendServerSupportedCurves: true,
11904			},
11905		},
11906	})
11907	testCases = append(testCases, testCase{
11908		name: "SupportedCurves-EncryptedExtensions-TLS13",
11909		config: Config{
11910			MaxVersion: VersionTLS13,
11911			Bugs: ProtocolBugs{
11912				SendServerSupportedCurves: true,
11913			},
11914		},
11915	})
11916
11917	// Test that we tolerate unknown point formats, as long as
11918	// pointFormatUncompressed is present. Limit ciphers to ECDHE ciphers to
11919	// check they are still functional.
11920	testCases = append(testCases, testCase{
11921		name: "PointFormat-Client-Tolerance",
11922		config: Config{
11923			MaxVersion: VersionTLS12,
11924			Bugs: ProtocolBugs{
11925				SendSupportedPointFormats: []byte{42, pointFormatUncompressed, 99, pointFormatCompressedPrime},
11926			},
11927		},
11928	})
11929	testCases = append(testCases, testCase{
11930		testType: serverTest,
11931		name:     "PointFormat-Server-Tolerance",
11932		config: Config{
11933			MaxVersion:   VersionTLS12,
11934			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
11935			Bugs: ProtocolBugs{
11936				SendSupportedPointFormats: []byte{42, pointFormatUncompressed, 99, pointFormatCompressedPrime},
11937			},
11938		},
11939	})
11940
11941	// Test TLS 1.2 does not require the point format extension to be
11942	// present.
11943	testCases = append(testCases, testCase{
11944		name: "PointFormat-Client-Missing",
11945		config: Config{
11946			MaxVersion:   VersionTLS12,
11947			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
11948			Bugs: ProtocolBugs{
11949				SendSupportedPointFormats: []byte{},
11950			},
11951		},
11952	})
11953	testCases = append(testCases, testCase{
11954		testType: serverTest,
11955		name:     "PointFormat-Server-Missing",
11956		config: Config{
11957			MaxVersion:   VersionTLS12,
11958			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
11959			Bugs: ProtocolBugs{
11960				SendSupportedPointFormats: []byte{},
11961			},
11962		},
11963	})
11964
11965	// If the point format extension is present, uncompressed points must be
11966	// offered. BoringSSL requires this whether or not ECDHE is used.
11967	testCases = append(testCases, testCase{
11968		name: "PointFormat-Client-MissingUncompressed",
11969		config: Config{
11970			MaxVersion: VersionTLS12,
11971			Bugs: ProtocolBugs{
11972				SendSupportedPointFormats: []byte{pointFormatCompressedPrime},
11973			},
11974		},
11975		shouldFail:    true,
11976		expectedError: ":ERROR_PARSING_EXTENSION:",
11977	})
11978	testCases = append(testCases, testCase{
11979		testType: serverTest,
11980		name:     "PointFormat-Server-MissingUncompressed",
11981		config: Config{
11982			MaxVersion: VersionTLS12,
11983			Bugs: ProtocolBugs{
11984				SendSupportedPointFormats: []byte{pointFormatCompressedPrime},
11985			},
11986		},
11987		shouldFail:    true,
11988		expectedError: ":ERROR_PARSING_EXTENSION:",
11989	})
11990
11991	// Implementations should mask off the high order bit in X25519.
11992	testCases = append(testCases, testCase{
11993		name: "SetX25519HighBit",
11994		config: Config{
11995			CipherSuites: []uint16{
11996				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
11997				TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
11998				TLS_AES_128_GCM_SHA256,
11999			},
12000			CurvePreferences: []CurveID{CurveX25519},
12001			Bugs: ProtocolBugs{
12002				SetX25519HighBit: true,
12003			},
12004		},
12005	})
12006
12007	// Kyber should not be offered by a TLS < 1.3 client.
12008	testCases = append(testCases, testCase{
12009		name: "KyberNotInTLS12",
12010		config: Config{
12011			Bugs: ProtocolBugs{
12012				FailIfKyberOffered: true,
12013			},
12014		},
12015		flags: []string{
12016			"-max-version", strconv.Itoa(VersionTLS12),
12017			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
12018			"-curves", strconv.Itoa(int(CurveX25519)),
12019		},
12020	})
12021
12022	// Kyber should not crash a TLS < 1.3 client if the server mistakenly
12023	// selects it.
12024	testCases = append(testCases, testCase{
12025		name: "KyberNotAcceptedByTLS12Client",
12026		config: Config{
12027			Bugs: ProtocolBugs{
12028				SendCurve: CurveX25519Kyber768,
12029			},
12030		},
12031		flags: []string{
12032			"-max-version", strconv.Itoa(VersionTLS12),
12033			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
12034			"-curves", strconv.Itoa(int(CurveX25519)),
12035		},
12036		shouldFail:    true,
12037		expectedError: ":WRONG_CURVE:",
12038	})
12039
12040	// Kyber should not be offered by default as a client.
12041	testCases = append(testCases, testCase{
12042		name: "KyberNotEnabledByDefaultInClients",
12043		config: Config{
12044			MinVersion: VersionTLS13,
12045			Bugs: ProtocolBugs{
12046				FailIfKyberOffered: true,
12047			},
12048		},
12049	})
12050
12051	// If Kyber is offered, both X25519 and Kyber should have a key-share.
12052	testCases = append(testCases, testCase{
12053		name: "NotJustKyberKeyShare",
12054		config: Config{
12055			MinVersion: VersionTLS13,
12056			Bugs: ProtocolBugs{
12057				ExpectedKeyShares: []CurveID{CurveX25519Kyber768, CurveX25519},
12058			},
12059		},
12060		flags: []string{
12061			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
12062			"-curves", strconv.Itoa(int(CurveX25519)),
12063			// Cannot expect Kyber until we have a Go implementation of it.
12064			// "-expect-curve-id", strconv.Itoa(int(CurveX25519Kyber768)),
12065		},
12066	})
12067
12068	// ... and the other way around
12069	testCases = append(testCases, testCase{
12070		name: "KyberKeyShareIncludedSecond",
12071		config: Config{
12072			MinVersion: VersionTLS13,
12073			Bugs: ProtocolBugs{
12074				ExpectedKeyShares: []CurveID{CurveX25519, CurveX25519Kyber768},
12075			},
12076		},
12077		flags: []string{
12078			"-curves", strconv.Itoa(int(CurveX25519)),
12079			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
12080			"-expect-curve-id", strconv.Itoa(int(CurveX25519)),
12081		},
12082	})
12083
12084	// ... and even if there's another curve in the middle because it's the
12085	// first classical and first post-quantum "curves" that get key shares
12086	// included.
12087	testCases = append(testCases, testCase{
12088		name: "KyberKeyShareIncludedThird",
12089		config: Config{
12090			MinVersion: VersionTLS13,
12091			Bugs: ProtocolBugs{
12092				ExpectedKeyShares: []CurveID{CurveX25519, CurveX25519Kyber768},
12093			},
12094		},
12095		flags: []string{
12096			"-curves", strconv.Itoa(int(CurveX25519)),
12097			"-curves", strconv.Itoa(int(CurveP256)),
12098			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
12099			"-expect-curve-id", strconv.Itoa(int(CurveX25519)),
12100		},
12101	})
12102
12103	// If Kyber is the only configured curve, the key share is sent.
12104	testCases = append(testCases, testCase{
12105		name: "JustConfiguringKyberWorks",
12106		config: Config{
12107			MinVersion: VersionTLS13,
12108			Bugs: ProtocolBugs{
12109				ExpectedKeyShares: []CurveID{CurveX25519Kyber768},
12110			},
12111		},
12112		flags: []string{
12113			"-curves", strconv.Itoa(int(CurveX25519Kyber768)),
12114			"-expect-curve-id", strconv.Itoa(int(CurveX25519Kyber768)),
12115		},
12116	})
12117
12118	// As a server, Kyber is not yet supported by default.
12119	testCases = append(testCases, testCase{
12120		testType: serverTest,
12121		name:     "KyberNotEnabledByDefaultForAServer",
12122		config: Config{
12123			MinVersion:       VersionTLS13,
12124			CurvePreferences: []CurveID{CurveX25519Kyber768, CurveX25519},
12125			DefaultCurves:    []CurveID{CurveX25519Kyber768},
12126		},
12127		flags: []string{
12128			"-server-preference",
12129			"-expect-curve-id", strconv.Itoa(int(CurveX25519)),
12130		},
12131	})
12132
12133	// In TLS 1.2, the curve list is also used to signal ECDSA curves.
12134	testCases = append(testCases, testCase{
12135		testType: serverTest,
12136		name:     "CheckECDSACurve-TLS12",
12137		config: Config{
12138			MinVersion:       VersionTLS12,
12139			MaxVersion:       VersionTLS12,
12140			CurvePreferences: []CurveID{CurveP384},
12141		},
12142		shimCertificate: &ecdsaP256Certificate,
12143		shouldFail:      true,
12144		expectedError:   ":WRONG_CURVE:",
12145	})
12146
12147	// This behavior may, temporarily, be disabled with a flag.
12148	testCases = append(testCases, testCase{
12149		testType: serverTest,
12150		name:     "NoCheckECDSACurve-TLS12",
12151		config: Config{
12152			MinVersion:       VersionTLS12,
12153			MaxVersion:       VersionTLS12,
12154			CurvePreferences: []CurveID{CurveP384},
12155		},
12156		shimCertificate: &ecdsaP256Certificate,
12157		flags:           []string{"-no-check-ecdsa-curve"},
12158	})
12159
12160	// If the ECDSA certificate is ineligible due to a curve mismatch, the
12161	// server may still consider a PSK cipher suite.
12162	testCases = append(testCases, testCase{
12163		testType: serverTest,
12164		name:     "CheckECDSACurve-PSK-TLS12",
12165		config: Config{
12166			MinVersion: VersionTLS12,
12167			MaxVersion: VersionTLS12,
12168			CipherSuites: []uint16{
12169				TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
12170				TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
12171			},
12172			CurvePreferences:     []CurveID{CurveP384},
12173			PreSharedKey:         []byte("12345"),
12174			PreSharedKeyIdentity: "luggage combo",
12175		},
12176		shimCertificate: &ecdsaP256Certificate,
12177		expectations: connectionExpectations{
12178			cipher: TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
12179		},
12180		flags: []string{
12181			"-psk", "12345",
12182			"-psk-identity", "luggage combo",
12183		},
12184	})
12185
12186	// In TLS 1.3, the curve list only controls ECDH.
12187	testCases = append(testCases, testCase{
12188		testType: serverTest,
12189		name:     "CheckECDSACurve-NotApplicable-TLS13",
12190		config: Config{
12191			MinVersion:       VersionTLS13,
12192			MaxVersion:       VersionTLS13,
12193			CurvePreferences: []CurveID{CurveP384},
12194		},
12195		shimCertificate: &ecdsaP256Certificate,
12196	})
12197}
12198
12199func addTLS13RecordTests() {
12200	testCases = append(testCases, testCase{
12201		name: "TLS13-RecordPadding",
12202		config: Config{
12203			MaxVersion: VersionTLS13,
12204			MinVersion: VersionTLS13,
12205			Bugs: ProtocolBugs{
12206				RecordPadding: 10,
12207			},
12208		},
12209	})
12210
12211	testCases = append(testCases, testCase{
12212		name: "TLS13-EmptyRecords",
12213		config: Config{
12214			MaxVersion: VersionTLS13,
12215			MinVersion: VersionTLS13,
12216			Bugs: ProtocolBugs{
12217				OmitRecordContents: true,
12218			},
12219		},
12220		shouldFail:    true,
12221		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
12222	})
12223
12224	testCases = append(testCases, testCase{
12225		name: "TLS13-OnlyPadding",
12226		config: Config{
12227			MaxVersion: VersionTLS13,
12228			MinVersion: VersionTLS13,
12229			Bugs: ProtocolBugs{
12230				OmitRecordContents: true,
12231				RecordPadding:      10,
12232			},
12233		},
12234		shouldFail:    true,
12235		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
12236	})
12237
12238	testCases = append(testCases, testCase{
12239		name: "TLS13-WrongOuterRecord",
12240		config: Config{
12241			MaxVersion: VersionTLS13,
12242			MinVersion: VersionTLS13,
12243			Bugs: ProtocolBugs{
12244				OuterRecordType: recordTypeHandshake,
12245			},
12246		},
12247		shouldFail:    true,
12248		expectedError: ":INVALID_OUTER_RECORD_TYPE:",
12249	})
12250}
12251
12252func addSessionTicketTests() {
12253	testCases = append(testCases, testCase{
12254		// In TLS 1.2 and below, empty NewSessionTicket messages
12255		// mean the server changed its mind on sending a ticket.
12256		name: "SendEmptySessionTicket",
12257		config: Config{
12258			MaxVersion: VersionTLS12,
12259			Bugs: ProtocolBugs{
12260				SendEmptySessionTicket: true,
12261			},
12262		},
12263		flags: []string{"-expect-no-session"},
12264	})
12265
12266	// Test that the server ignores unknown PSK modes.
12267	testCases = append(testCases, testCase{
12268		testType: serverTest,
12269		name:     "TLS13-SendUnknownModeSessionTicket-Server",
12270		config: Config{
12271			MaxVersion: VersionTLS13,
12272			Bugs: ProtocolBugs{
12273				SendPSKKeyExchangeModes: []byte{0x1a, pskDHEKEMode, 0x2a},
12274			},
12275		},
12276		resumeSession: true,
12277		expectations: connectionExpectations{
12278			version: VersionTLS13,
12279		},
12280	})
12281
12282	// Test that the server does not send session tickets with no matching key exchange mode.
12283	testCases = append(testCases, testCase{
12284		testType: serverTest,
12285		name:     "TLS13-ExpectNoSessionTicketOnBadKEMode-Server",
12286		config: Config{
12287			MaxVersion: VersionTLS13,
12288			Bugs: ProtocolBugs{
12289				SendPSKKeyExchangeModes:  []byte{0x1a},
12290				ExpectNoNewSessionTicket: true,
12291			},
12292		},
12293	})
12294
12295	// Test that the server does not accept a session with no matching key exchange mode.
12296	testCases = append(testCases, testCase{
12297		testType: serverTest,
12298		name:     "TLS13-SendBadKEModeSessionTicket-Server",
12299		config: Config{
12300			MaxVersion: VersionTLS13,
12301		},
12302		resumeConfig: &Config{
12303			MaxVersion: VersionTLS13,
12304			Bugs: ProtocolBugs{
12305				SendPSKKeyExchangeModes: []byte{0x1a},
12306			},
12307		},
12308		resumeSession:        true,
12309		expectResumeRejected: true,
12310	})
12311
12312	// Test that the server rejects ClientHellos with pre_shared_key but without
12313	// psk_key_exchange_modes.
12314	testCases = append(testCases, testCase{
12315		testType: serverTest,
12316		name:     "TLS13-SendNoKEMModesWithPSK-Server",
12317		config: Config{
12318			MaxVersion: VersionTLS13,
12319		},
12320		resumeConfig: &Config{
12321			MaxVersion: VersionTLS13,
12322			Bugs: ProtocolBugs{
12323				SendPSKKeyExchangeModes: []byte{},
12324			},
12325		},
12326		resumeSession:      true,
12327		shouldFail:         true,
12328		expectedLocalError: "remote error: missing extension",
12329		expectedError:      ":MISSING_EXTENSION:",
12330	})
12331
12332	// Test that the client ticket age is sent correctly.
12333	testCases = append(testCases, testCase{
12334		testType: clientTest,
12335		name:     "TLS13-TestValidTicketAge-Client",
12336		config: Config{
12337			MaxVersion: VersionTLS13,
12338			Bugs: ProtocolBugs{
12339				ExpectTicketAge: 10 * time.Second,
12340			},
12341		},
12342		resumeSession: true,
12343		flags: []string{
12344			"-resumption-delay", "10",
12345		},
12346	})
12347
12348	// Test that the client ticket age is enforced.
12349	testCases = append(testCases, testCase{
12350		testType: clientTest,
12351		name:     "TLS13-TestBadTicketAge-Client",
12352		config: Config{
12353			MaxVersion: VersionTLS13,
12354			Bugs: ProtocolBugs{
12355				ExpectTicketAge: 1000 * time.Second,
12356			},
12357		},
12358		resumeSession:      true,
12359		shouldFail:         true,
12360		expectedLocalError: "tls: invalid ticket age",
12361	})
12362
12363	// Test that the server's ticket age skew reporting works.
12364	testCases = append(testCases, testCase{
12365		testType: serverTest,
12366		name:     "TLS13-TicketAgeSkew-Forward",
12367		config: Config{
12368			MaxVersion: VersionTLS13,
12369			Bugs: ProtocolBugs{
12370				SendTicketAge: 15 * time.Second,
12371			},
12372		},
12373		resumeSession:        true,
12374		resumeRenewedSession: true,
12375		flags: []string{
12376			"-resumption-delay", "10",
12377			"-expect-ticket-age-skew", "5",
12378		},
12379	})
12380	testCases = append(testCases, testCase{
12381		testType: serverTest,
12382		name:     "TLS13-TicketAgeSkew-Backward",
12383		config: Config{
12384			MaxVersion: VersionTLS13,
12385			Bugs: ProtocolBugs{
12386				SendTicketAge: 5 * time.Second,
12387			},
12388		},
12389		resumeSession:        true,
12390		resumeRenewedSession: true,
12391		flags: []string{
12392			"-resumption-delay", "10",
12393			"-expect-ticket-age-skew", "-5",
12394		},
12395	})
12396
12397	// Test that ticket age skew up to 60 seconds in either direction is accepted.
12398	testCases = append(testCases, testCase{
12399		testType: serverTest,
12400		name:     "TLS13-TicketAgeSkew-Forward-60-Accept",
12401		config: Config{
12402			MaxVersion: VersionTLS13,
12403			Bugs: ProtocolBugs{
12404				SendTicketAge: 70 * time.Second,
12405			},
12406		},
12407		resumeSession: true,
12408		earlyData:     true,
12409		flags: []string{
12410			"-resumption-delay", "10",
12411			"-expect-ticket-age-skew", "60",
12412		},
12413	})
12414	testCases = append(testCases, testCase{
12415		testType: serverTest,
12416		name:     "TLS13-TicketAgeSkew-Backward-60-Accept",
12417		config: Config{
12418			MaxVersion: VersionTLS13,
12419			Bugs: ProtocolBugs{
12420				SendTicketAge: 10 * time.Second,
12421			},
12422		},
12423		resumeSession: true,
12424		earlyData:     true,
12425		flags: []string{
12426			"-resumption-delay", "70",
12427			"-expect-ticket-age-skew", "-60",
12428		},
12429	})
12430
12431	// Test that ticket age skew beyond 60 seconds in either direction is rejected.
12432	testCases = append(testCases, testCase{
12433		testType: serverTest,
12434		name:     "TLS13-TicketAgeSkew-Forward-61-Reject",
12435		config: Config{
12436			MaxVersion: VersionTLS13,
12437			Bugs: ProtocolBugs{
12438				SendTicketAge: 71 * time.Second,
12439			},
12440		},
12441		resumeSession:           true,
12442		earlyData:               true,
12443		expectEarlyDataRejected: true,
12444		flags: []string{
12445			"-resumption-delay", "10",
12446			"-expect-ticket-age-skew", "61",
12447			"-on-resume-expect-early-data-reason", "ticket_age_skew",
12448		},
12449	})
12450	testCases = append(testCases, testCase{
12451		testType: serverTest,
12452		name:     "TLS13-TicketAgeSkew-Backward-61-Reject",
12453		config: Config{
12454			MaxVersion: VersionTLS13,
12455			Bugs: ProtocolBugs{
12456				SendTicketAge: 10 * time.Second,
12457			},
12458		},
12459		resumeSession:           true,
12460		earlyData:               true,
12461		expectEarlyDataRejected: true,
12462		flags: []string{
12463			"-resumption-delay", "71",
12464			"-expect-ticket-age-skew", "-61",
12465			"-on-resume-expect-early-data-reason", "ticket_age_skew",
12466		},
12467	})
12468
12469	testCases = append(testCases, testCase{
12470		testType: clientTest,
12471		name:     "TLS13-SendTicketEarlyDataSupport",
12472		config: Config{
12473			MaxVersion:       VersionTLS13,
12474			MaxEarlyDataSize: 16384,
12475		},
12476		flags: []string{
12477			"-enable-early-data",
12478			"-expect-ticket-supports-early-data",
12479		},
12480	})
12481
12482	// Test that 0-RTT tickets are still recorded as such when early data is disabled overall.
12483	testCases = append(testCases, testCase{
12484		testType: clientTest,
12485		name:     "TLS13-SendTicketEarlyDataSupport-Disabled",
12486		config: Config{
12487			MaxVersion:       VersionTLS13,
12488			MaxEarlyDataSize: 16384,
12489		},
12490		flags: []string{
12491			"-expect-ticket-supports-early-data",
12492		},
12493	})
12494
12495	testCases = append(testCases, testCase{
12496		testType: clientTest,
12497		name:     "TLS13-DuplicateTicketEarlyDataSupport",
12498		config: Config{
12499			MaxVersion:       VersionTLS13,
12500			MaxEarlyDataSize: 16384,
12501			Bugs: ProtocolBugs{
12502				DuplicateTicketEarlyData: true,
12503			},
12504		},
12505		shouldFail:         true,
12506		expectedError:      ":DUPLICATE_EXTENSION:",
12507		expectedLocalError: "remote error: illegal parameter",
12508	})
12509
12510	testCases = append(testCases, testCase{
12511		testType: serverTest,
12512		name:     "TLS13-ExpectTicketEarlyDataSupport",
12513		config: Config{
12514			MaxVersion: VersionTLS13,
12515			Bugs: ProtocolBugs{
12516				ExpectTicketEarlyData: true,
12517			},
12518		},
12519		flags: []string{
12520			"-enable-early-data",
12521		},
12522	})
12523
12524	// Test that, in TLS 1.3, the server-offered NewSessionTicket lifetime
12525	// is honored.
12526	testCases = append(testCases, testCase{
12527		testType: clientTest,
12528		name:     "TLS13-HonorServerSessionTicketLifetime",
12529		config: Config{
12530			MaxVersion: VersionTLS13,
12531			Bugs: ProtocolBugs{
12532				SendTicketLifetime: 20 * time.Second,
12533			},
12534		},
12535		flags: []string{
12536			"-resumption-delay", "19",
12537		},
12538		resumeSession: true,
12539	})
12540	testCases = append(testCases, testCase{
12541		testType: clientTest,
12542		name:     "TLS13-HonorServerSessionTicketLifetime-2",
12543		config: Config{
12544			MaxVersion: VersionTLS13,
12545			Bugs: ProtocolBugs{
12546				SendTicketLifetime: 20 * time.Second,
12547				// The client should not offer the expired session.
12548				ExpectNoTLS13PSK: true,
12549			},
12550		},
12551		flags: []string{
12552			"-resumption-delay", "21",
12553		},
12554		resumeSession:        true,
12555		expectResumeRejected: true,
12556	})
12557
12558	for _, ver := range tlsVersions {
12559		// Prior to TLS 1.3, disabling session tickets enables session IDs.
12560		useStatefulResumption := ver.version < VersionTLS13
12561
12562		// SSL_OP_NO_TICKET implies the server must not mint any tickets.
12563		testCases = append(testCases, testCase{
12564			testType: serverTest,
12565			name:     ver.name + "-NoTicket-NoMint",
12566			config: Config{
12567				MinVersion: ver.version,
12568				MaxVersion: ver.version,
12569				Bugs: ProtocolBugs{
12570					ExpectNoNewSessionTicket: true,
12571					RequireSessionIDs:        useStatefulResumption,
12572				},
12573			},
12574			resumeSession: useStatefulResumption,
12575			flags:         []string{"-no-ticket"},
12576		})
12577
12578		// SSL_OP_NO_TICKET implies the server must not accept any tickets.
12579		testCases = append(testCases, testCase{
12580			testType: serverTest,
12581			name:     ver.name + "-NoTicket-NoAccept",
12582			config: Config{
12583				MinVersion: ver.version,
12584				MaxVersion: ver.version,
12585			},
12586			resumeSession:        true,
12587			expectResumeRejected: true,
12588			// Set SSL_OP_NO_TICKET on the second connection, after the first
12589			// has established tickets.
12590			flags: []string{"-on-resume-no-ticket"},
12591		})
12592	}
12593}
12594
12595func addChangeCipherSpecTests() {
12596	// Test missing ChangeCipherSpecs.
12597	testCases = append(testCases, testCase{
12598		name: "SkipChangeCipherSpec-Client",
12599		config: Config{
12600			MaxVersion: VersionTLS12,
12601			Bugs: ProtocolBugs{
12602				SkipChangeCipherSpec: true,
12603			},
12604		},
12605		shouldFail:    true,
12606		expectedError: ":UNEXPECTED_RECORD:",
12607	})
12608	testCases = append(testCases, testCase{
12609		testType: serverTest,
12610		name:     "SkipChangeCipherSpec-Server",
12611		config: Config{
12612			MaxVersion: VersionTLS12,
12613			Bugs: ProtocolBugs{
12614				SkipChangeCipherSpec: true,
12615			},
12616		},
12617		shouldFail:    true,
12618		expectedError: ":UNEXPECTED_RECORD:",
12619	})
12620	testCases = append(testCases, testCase{
12621		testType: serverTest,
12622		name:     "SkipChangeCipherSpec-Server-NPN",
12623		config: Config{
12624			MaxVersion: VersionTLS12,
12625			NextProtos: []string{"bar"},
12626			Bugs: ProtocolBugs{
12627				SkipChangeCipherSpec: true,
12628			},
12629		},
12630		flags: []string{
12631			"-advertise-npn", "\x03foo\x03bar\x03baz",
12632		},
12633		shouldFail:    true,
12634		expectedError: ":UNEXPECTED_RECORD:",
12635	})
12636
12637	// Test synchronization between the handshake and ChangeCipherSpec.
12638	// Partial post-CCS handshake messages before ChangeCipherSpec should be
12639	// rejected. Test both with and without handshake packing to handle both
12640	// when the partial post-CCS message is in its own record and when it is
12641	// attached to the pre-CCS message.
12642	for _, packed := range []bool{false, true} {
12643		var suffix string
12644		if packed {
12645			suffix = "-Packed"
12646		}
12647
12648		testCases = append(testCases, testCase{
12649			name: "FragmentAcrossChangeCipherSpec-Client" + suffix,
12650			config: Config{
12651				MaxVersion: VersionTLS12,
12652				Bugs: ProtocolBugs{
12653					FragmentAcrossChangeCipherSpec: true,
12654					PackHandshakeFlight:            packed,
12655				},
12656			},
12657			shouldFail:    true,
12658			expectedError: ":UNEXPECTED_RECORD:",
12659		})
12660		testCases = append(testCases, testCase{
12661			name: "FragmentAcrossChangeCipherSpec-Client-Resume" + suffix,
12662			config: Config{
12663				MaxVersion: VersionTLS12,
12664			},
12665			resumeSession: true,
12666			resumeConfig: &Config{
12667				MaxVersion: VersionTLS12,
12668				Bugs: ProtocolBugs{
12669					FragmentAcrossChangeCipherSpec: true,
12670					PackHandshakeFlight:            packed,
12671				},
12672			},
12673			shouldFail:    true,
12674			expectedError: ":UNEXPECTED_RECORD:",
12675		})
12676		testCases = append(testCases, testCase{
12677			testType: serverTest,
12678			name:     "FragmentAcrossChangeCipherSpec-Server" + suffix,
12679			config: Config{
12680				MaxVersion: VersionTLS12,
12681				Bugs: ProtocolBugs{
12682					FragmentAcrossChangeCipherSpec: true,
12683					PackHandshakeFlight:            packed,
12684				},
12685			},
12686			shouldFail:    true,
12687			expectedError: ":UNEXPECTED_RECORD:",
12688		})
12689		testCases = append(testCases, testCase{
12690			testType: serverTest,
12691			name:     "FragmentAcrossChangeCipherSpec-Server-Resume" + suffix,
12692			config: Config{
12693				MaxVersion: VersionTLS12,
12694			},
12695			resumeSession: true,
12696			resumeConfig: &Config{
12697				MaxVersion: VersionTLS12,
12698				Bugs: ProtocolBugs{
12699					FragmentAcrossChangeCipherSpec: true,
12700					PackHandshakeFlight:            packed,
12701				},
12702			},
12703			shouldFail:    true,
12704			expectedError: ":UNEXPECTED_RECORD:",
12705		})
12706		testCases = append(testCases, testCase{
12707			testType: serverTest,
12708			name:     "FragmentAcrossChangeCipherSpec-Server-NPN" + suffix,
12709			config: Config{
12710				MaxVersion: VersionTLS12,
12711				NextProtos: []string{"bar"},
12712				Bugs: ProtocolBugs{
12713					FragmentAcrossChangeCipherSpec: true,
12714					PackHandshakeFlight:            packed,
12715				},
12716			},
12717			flags: []string{
12718				"-advertise-npn", "\x03foo\x03bar\x03baz",
12719			},
12720			shouldFail:    true,
12721			expectedError: ":UNEXPECTED_RECORD:",
12722		})
12723	}
12724
12725	// In TLS 1.2 resumptions, the client sends ClientHello in the first flight
12726	// and ChangeCipherSpec + Finished in the second flight. Test the server's
12727	// behavior when the Finished message is fragmented across not only
12728	// ChangeCipherSpec but also the flight boundary.
12729	testCases = append(testCases, testCase{
12730		testType: serverTest,
12731		name:     "PartialClientFinishedWithClientHello-TLS12-Resume",
12732		config: Config{
12733			MaxVersion: VersionTLS12,
12734		},
12735		resumeConfig: &Config{
12736			MaxVersion: VersionTLS12,
12737			Bugs: ProtocolBugs{
12738				PartialClientFinishedWithClientHello: true,
12739			},
12740		},
12741		resumeSession:      true,
12742		shouldFail:         true,
12743		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
12744		expectedLocalError: "remote error: unexpected message",
12745	})
12746
12747	// In TLS 1.2 full handshakes without tickets, the server's first flight ends
12748	// with ServerHelloDone and the second flight is ChangeCipherSpec + Finished.
12749	// Test the client's behavior when the Finished message is fragmented across
12750	// not only ChangeCipherSpec but also the flight boundary.
12751	testCases = append(testCases, testCase{
12752		testType: clientTest,
12753		name:     "PartialFinishedWithServerHelloDone",
12754		config: Config{
12755			MaxVersion:             VersionTLS12,
12756			SessionTicketsDisabled: true,
12757			Bugs: ProtocolBugs{
12758				PartialFinishedWithServerHelloDone: true,
12759			},
12760		},
12761		shouldFail:         true,
12762		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
12763		expectedLocalError: "remote error: unexpected message",
12764	})
12765
12766	// Test that, in DTLS, ChangeCipherSpec is not allowed when there are
12767	// messages in the handshake queue. Do this by testing the server
12768	// reading the client Finished, reversing the flight so Finished comes
12769	// first.
12770	testCases = append(testCases, testCase{
12771		protocol: dtls,
12772		testType: serverTest,
12773		name:     "SendUnencryptedFinished-DTLS",
12774		config: Config{
12775			MaxVersion: VersionTLS12,
12776			Bugs: ProtocolBugs{
12777				SendUnencryptedFinished:   true,
12778				ReverseHandshakeFragments: true,
12779			},
12780		},
12781		shouldFail:    true,
12782		expectedError: ":EXCESS_HANDSHAKE_DATA:",
12783	})
12784
12785	// Test synchronization between encryption changes and the handshake in
12786	// TLS 1.3, where ChangeCipherSpec is implicit.
12787	testCases = append(testCases, testCase{
12788		name: "PartialEncryptedExtensionsWithServerHello",
12789		config: Config{
12790			MaxVersion: VersionTLS13,
12791			Bugs: ProtocolBugs{
12792				PartialEncryptedExtensionsWithServerHello: true,
12793			},
12794		},
12795		shouldFail:    true,
12796		expectedError: ":EXCESS_HANDSHAKE_DATA:",
12797	})
12798	testCases = append(testCases, testCase{
12799		testType: serverTest,
12800		name:     "PartialClientFinishedWithClientHello",
12801		config: Config{
12802			MaxVersion: VersionTLS13,
12803			Bugs: ProtocolBugs{
12804				PartialClientFinishedWithClientHello: true,
12805			},
12806		},
12807		shouldFail:    true,
12808		expectedError: ":EXCESS_HANDSHAKE_DATA:",
12809	})
12810	testCases = append(testCases, testCase{
12811		testType: serverTest,
12812		name:     "PartialClientFinishedWithSecondClientHello",
12813		config: Config{
12814			MaxVersion: VersionTLS13,
12815			// Trigger a curve-based HelloRetryRequest.
12816			DefaultCurves: []CurveID{},
12817			Bugs: ProtocolBugs{
12818				PartialClientFinishedWithSecondClientHello: true,
12819			},
12820		},
12821		shouldFail:    true,
12822		expectedError: ":EXCESS_HANDSHAKE_DATA:",
12823	})
12824	testCases = append(testCases, testCase{
12825		testType: serverTest,
12826		name:     "PartialEndOfEarlyDataWithClientHello",
12827		config: Config{
12828			MaxVersion: VersionTLS13,
12829		},
12830		resumeConfig: &Config{
12831			MaxVersion: VersionTLS13,
12832			Bugs: ProtocolBugs{
12833				PartialEndOfEarlyDataWithClientHello: true,
12834			},
12835		},
12836		resumeSession: true,
12837		earlyData:     true,
12838		shouldFail:    true,
12839		expectedError: ":EXCESS_HANDSHAKE_DATA:",
12840	})
12841
12842	// Test that early ChangeCipherSpecs are handled correctly.
12843	testCases = append(testCases, testCase{
12844		testType: serverTest,
12845		name:     "EarlyChangeCipherSpec-server-1",
12846		config: Config{
12847			MaxVersion: VersionTLS12,
12848			Bugs: ProtocolBugs{
12849				EarlyChangeCipherSpec: 1,
12850			},
12851		},
12852		shouldFail:    true,
12853		expectedError: ":UNEXPECTED_RECORD:",
12854	})
12855	testCases = append(testCases, testCase{
12856		testType: serverTest,
12857		name:     "EarlyChangeCipherSpec-server-2",
12858		config: Config{
12859			MaxVersion: VersionTLS12,
12860			Bugs: ProtocolBugs{
12861				EarlyChangeCipherSpec: 2,
12862			},
12863		},
12864		shouldFail:    true,
12865		expectedError: ":UNEXPECTED_RECORD:",
12866	})
12867	testCases = append(testCases, testCase{
12868		protocol: dtls,
12869		name:     "StrayChangeCipherSpec",
12870		config: Config{
12871			// TODO(davidben): Once DTLS 1.3 exists, test
12872			// that stray ChangeCipherSpec messages are
12873			// rejected.
12874			MaxVersion: VersionTLS12,
12875			Bugs: ProtocolBugs{
12876				StrayChangeCipherSpec: true,
12877			},
12878		},
12879	})
12880
12881	// Test that reordered ChangeCipherSpecs are tolerated.
12882	testCases = append(testCases, testCase{
12883		protocol: dtls,
12884		name:     "ReorderChangeCipherSpec-DTLS-Client",
12885		config: Config{
12886			MaxVersion: VersionTLS12,
12887			Bugs: ProtocolBugs{
12888				ReorderChangeCipherSpec: true,
12889			},
12890		},
12891		resumeSession: true,
12892	})
12893	testCases = append(testCases, testCase{
12894		testType: serverTest,
12895		protocol: dtls,
12896		name:     "ReorderChangeCipherSpec-DTLS-Server",
12897		config: Config{
12898			MaxVersion: VersionTLS12,
12899			Bugs: ProtocolBugs{
12900				ReorderChangeCipherSpec: true,
12901			},
12902		},
12903		resumeSession: true,
12904	})
12905
12906	// Test that the contents of ChangeCipherSpec are checked.
12907	testCases = append(testCases, testCase{
12908		name: "BadChangeCipherSpec-1",
12909		config: Config{
12910			MaxVersion: VersionTLS12,
12911			Bugs: ProtocolBugs{
12912				BadChangeCipherSpec: []byte{2},
12913			},
12914		},
12915		shouldFail:    true,
12916		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
12917	})
12918	testCases = append(testCases, testCase{
12919		name: "BadChangeCipherSpec-2",
12920		config: Config{
12921			MaxVersion: VersionTLS12,
12922			Bugs: ProtocolBugs{
12923				BadChangeCipherSpec: []byte{1, 1},
12924			},
12925		},
12926		shouldFail:    true,
12927		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
12928	})
12929	testCases = append(testCases, testCase{
12930		protocol: dtls,
12931		name:     "BadChangeCipherSpec-DTLS-1",
12932		config: Config{
12933			MaxVersion: VersionTLS12,
12934			Bugs: ProtocolBugs{
12935				BadChangeCipherSpec: []byte{2},
12936			},
12937		},
12938		shouldFail:    true,
12939		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
12940	})
12941	testCases = append(testCases, testCase{
12942		protocol: dtls,
12943		name:     "BadChangeCipherSpec-DTLS-2",
12944		config: Config{
12945			MaxVersion: VersionTLS12,
12946			Bugs: ProtocolBugs{
12947				BadChangeCipherSpec: []byte{1, 1},
12948			},
12949		},
12950		shouldFail:    true,
12951		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
12952	})
12953}
12954
12955// addEndOfFlightTests adds tests where the runner adds extra data in the final
12956// record of each handshake flight. Depending on the implementation strategy,
12957// this data may be carried over to the next flight (assuming no key change) or
12958// may be rejected. To avoid differences with split handshakes and generally
12959// reject misbehavior, BoringSSL treats this as an error. When possible, these
12960// tests pull the extra data from the subsequent flight to distinguish the data
12961// being carried over from a general syntax error.
12962//
12963// These tests are similar to tests in |addChangeCipherSpecTests| that send
12964// extra data at key changes. Not all key changes are at the end of a flight and
12965// not all flights end at a key change.
12966func addEndOfFlightTests() {
12967	// TLS 1.3 client handshakes.
12968	//
12969	// Data following the second TLS 1.3 ClientHello is covered by
12970	// PartialClientFinishedWithClientHello,
12971	// PartialClientFinishedWithSecondClientHello, and
12972	// PartialEndOfEarlyDataWithClientHello in |addChangeCipherSpecTests|.
12973	testCases = append(testCases, testCase{
12974		testType: serverTest,
12975		name:     "PartialSecondClientHelloAfterFirst",
12976		config: Config{
12977			MaxVersion: VersionTLS13,
12978			// Trigger a curve-based HelloRetryRequest.
12979			DefaultCurves: []CurveID{},
12980			Bugs: ProtocolBugs{
12981				PartialSecondClientHelloAfterFirst: true,
12982			},
12983		},
12984		shouldFail:         true,
12985		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
12986		expectedLocalError: "remote error: unexpected message",
12987	})
12988
12989	// TLS 1.3 server handshakes.
12990	testCases = append(testCases, testCase{
12991		testType: clientTest,
12992		name:     "PartialServerHelloWithHelloRetryRequest",
12993		config: Config{
12994			MaxVersion: VersionTLS13,
12995			// P-384 requires HelloRetryRequest in BoringSSL.
12996			CurvePreferences: []CurveID{CurveP384},
12997			Bugs: ProtocolBugs{
12998				PartialServerHelloWithHelloRetryRequest: true,
12999			},
13000		},
13001		shouldFail:         true,
13002		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
13003		expectedLocalError: "remote error: unexpected message",
13004	})
13005
13006	// TLS 1.2 client handshakes.
13007	testCases = append(testCases, testCase{
13008		testType: serverTest,
13009		name:     "PartialClientKeyExchangeWithClientHello",
13010		config: Config{
13011			MaxVersion: VersionTLS12,
13012			Bugs: ProtocolBugs{
13013				PartialClientKeyExchangeWithClientHello: true,
13014			},
13015		},
13016		shouldFail:         true,
13017		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
13018		expectedLocalError: "remote error: unexpected message",
13019	})
13020
13021	// TLS 1.2 server handshakes.
13022	testCases = append(testCases, testCase{
13023		testType: clientTest,
13024		name:     "PartialNewSessionTicketWithServerHelloDone",
13025		config: Config{
13026			MaxVersion: VersionTLS12,
13027			Bugs: ProtocolBugs{
13028				PartialNewSessionTicketWithServerHelloDone: true,
13029			},
13030		},
13031		shouldFail:         true,
13032		expectedError:      ":EXCESS_HANDSHAKE_DATA:",
13033		expectedLocalError: "remote error: unexpected message",
13034	})
13035
13036	for _, vers := range tlsVersions {
13037		for _, testType := range []testType{clientTest, serverTest} {
13038			suffix := "-Client"
13039			if testType == serverTest {
13040				suffix = "-Server"
13041			}
13042			suffix += "-" + vers.name
13043
13044			testCases = append(testCases, testCase{
13045				testType: testType,
13046				name:     "TrailingDataWithFinished" + suffix,
13047				config: Config{
13048					MaxVersion: vers.version,
13049					Bugs: ProtocolBugs{
13050						TrailingDataWithFinished: true,
13051					},
13052				},
13053				shouldFail:         true,
13054				expectedError:      ":EXCESS_HANDSHAKE_DATA:",
13055				expectedLocalError: "remote error: unexpected message",
13056			})
13057			testCases = append(testCases, testCase{
13058				testType: testType,
13059				name:     "TrailingDataWithFinished-Resume" + suffix,
13060				config: Config{
13061					MaxVersion: vers.version,
13062				},
13063				resumeConfig: &Config{
13064					MaxVersion: vers.version,
13065					Bugs: ProtocolBugs{
13066						TrailingDataWithFinished: true,
13067					},
13068				},
13069				resumeSession:      true,
13070				shouldFail:         true,
13071				expectedError:      ":EXCESS_HANDSHAKE_DATA:",
13072				expectedLocalError: "remote error: unexpected message",
13073			})
13074		}
13075	}
13076}
13077
13078type perMessageTest struct {
13079	messageType uint8
13080	test        testCase
13081}
13082
13083// makePerMessageTests returns a series of test templates which cover each
13084// message in the TLS handshake. These may be used with bugs like
13085// WrongMessageType to fully test a per-message bug.
13086func makePerMessageTests() []perMessageTest {
13087	var ret []perMessageTest
13088	// The following tests are limited to TLS 1.2, so QUIC is not tested.
13089	for _, protocol := range []protocol{tls, dtls} {
13090		suffix := "-" + protocol.String()
13091
13092		ret = append(ret, perMessageTest{
13093			messageType: typeClientHello,
13094			test: testCase{
13095				protocol: protocol,
13096				testType: serverTest,
13097				name:     "ClientHello" + suffix,
13098				config: Config{
13099					MaxVersion: VersionTLS12,
13100				},
13101			},
13102		})
13103
13104		if protocol == dtls {
13105			ret = append(ret, perMessageTest{
13106				messageType: typeHelloVerifyRequest,
13107				test: testCase{
13108					protocol: protocol,
13109					name:     "HelloVerifyRequest" + suffix,
13110					config: Config{
13111						MaxVersion: VersionTLS12,
13112					},
13113				},
13114			})
13115		}
13116
13117		ret = append(ret, perMessageTest{
13118			messageType: typeServerHello,
13119			test: testCase{
13120				protocol: protocol,
13121				name:     "ServerHello" + suffix,
13122				config: Config{
13123					MaxVersion: VersionTLS12,
13124				},
13125			},
13126		})
13127
13128		ret = append(ret, perMessageTest{
13129			messageType: typeCertificate,
13130			test: testCase{
13131				protocol: protocol,
13132				name:     "ServerCertificate" + suffix,
13133				config: Config{
13134					MaxVersion: VersionTLS12,
13135				},
13136			},
13137		})
13138
13139		ret = append(ret, perMessageTest{
13140			messageType: typeCertificateStatus,
13141			test: testCase{
13142				protocol: protocol,
13143				name:     "CertificateStatus" + suffix,
13144				config: Config{
13145					MaxVersion: VersionTLS12,
13146					Credential: rsaCertificate.WithOCSP(testOCSPResponse),
13147				},
13148				flags: []string{"-enable-ocsp-stapling"},
13149			},
13150		})
13151
13152		ret = append(ret, perMessageTest{
13153			messageType: typeServerKeyExchange,
13154			test: testCase{
13155				protocol: protocol,
13156				name:     "ServerKeyExchange" + suffix,
13157				config: Config{
13158					MaxVersion:   VersionTLS12,
13159					CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
13160				},
13161			},
13162		})
13163
13164		ret = append(ret, perMessageTest{
13165			messageType: typeCertificateRequest,
13166			test: testCase{
13167				protocol: protocol,
13168				name:     "CertificateRequest" + suffix,
13169				config: Config{
13170					MaxVersion: VersionTLS12,
13171					ClientAuth: RequireAnyClientCert,
13172				},
13173			},
13174		})
13175
13176		ret = append(ret, perMessageTest{
13177			messageType: typeServerHelloDone,
13178			test: testCase{
13179				protocol: protocol,
13180				name:     "ServerHelloDone" + suffix,
13181				config: Config{
13182					MaxVersion: VersionTLS12,
13183				},
13184			},
13185		})
13186
13187		ret = append(ret, perMessageTest{
13188			messageType: typeCertificate,
13189			test: testCase{
13190				testType: serverTest,
13191				protocol: protocol,
13192				name:     "ClientCertificate" + suffix,
13193				config: Config{
13194					Credential: &rsaCertificate,
13195					MaxVersion: VersionTLS12,
13196				},
13197				flags: []string{"-require-any-client-certificate"},
13198			},
13199		})
13200
13201		ret = append(ret, perMessageTest{
13202			messageType: typeCertificateVerify,
13203			test: testCase{
13204				testType: serverTest,
13205				protocol: protocol,
13206				name:     "CertificateVerify" + suffix,
13207				config: Config{
13208					Credential: &rsaCertificate,
13209					MaxVersion: VersionTLS12,
13210				},
13211				flags: []string{"-require-any-client-certificate"},
13212			},
13213		})
13214
13215		ret = append(ret, perMessageTest{
13216			messageType: typeClientKeyExchange,
13217			test: testCase{
13218				testType: serverTest,
13219				protocol: protocol,
13220				name:     "ClientKeyExchange" + suffix,
13221				config: Config{
13222					MaxVersion: VersionTLS12,
13223				},
13224			},
13225		})
13226
13227		if protocol != dtls {
13228			ret = append(ret, perMessageTest{
13229				messageType: typeNextProtocol,
13230				test: testCase{
13231					testType: serverTest,
13232					protocol: protocol,
13233					name:     "NextProtocol" + suffix,
13234					config: Config{
13235						MaxVersion: VersionTLS12,
13236						NextProtos: []string{"bar"},
13237					},
13238					flags: []string{"-advertise-npn", "\x03foo\x03bar\x03baz"},
13239				},
13240			})
13241
13242			ret = append(ret, perMessageTest{
13243				messageType: typeChannelID,
13244				test: testCase{
13245					testType: serverTest,
13246					protocol: protocol,
13247					name:     "ChannelID" + suffix,
13248					config: Config{
13249						MaxVersion: VersionTLS12,
13250						ChannelID:  &channelIDKey,
13251					},
13252					flags: []string{
13253						"-expect-channel-id",
13254						base64FlagValue(channelIDBytes),
13255					},
13256				},
13257			})
13258		}
13259
13260		ret = append(ret, perMessageTest{
13261			messageType: typeFinished,
13262			test: testCase{
13263				testType: serverTest,
13264				protocol: protocol,
13265				name:     "ClientFinished" + suffix,
13266				config: Config{
13267					MaxVersion: VersionTLS12,
13268				},
13269			},
13270		})
13271
13272		ret = append(ret, perMessageTest{
13273			messageType: typeNewSessionTicket,
13274			test: testCase{
13275				protocol: protocol,
13276				name:     "NewSessionTicket" + suffix,
13277				config: Config{
13278					MaxVersion: VersionTLS12,
13279				},
13280			},
13281		})
13282
13283		ret = append(ret, perMessageTest{
13284			messageType: typeFinished,
13285			test: testCase{
13286				protocol: protocol,
13287				name:     "ServerFinished" + suffix,
13288				config: Config{
13289					MaxVersion: VersionTLS12,
13290				},
13291			},
13292		})
13293
13294	}
13295
13296	for _, protocol := range []protocol{tls, quic} {
13297		suffix := "-" + protocol.String()
13298		ret = append(ret, perMessageTest{
13299			messageType: typeClientHello,
13300			test: testCase{
13301				testType: serverTest,
13302				protocol: protocol,
13303				name:     "TLS13-ClientHello" + suffix,
13304				config: Config{
13305					MaxVersion: VersionTLS13,
13306				},
13307			},
13308		})
13309
13310		ret = append(ret, perMessageTest{
13311			messageType: typeServerHello,
13312			test: testCase{
13313				name:     "TLS13-ServerHello" + suffix,
13314				protocol: protocol,
13315				config: Config{
13316					MaxVersion: VersionTLS13,
13317				},
13318			},
13319		})
13320
13321		ret = append(ret, perMessageTest{
13322			messageType: typeEncryptedExtensions,
13323			test: testCase{
13324				name:     "TLS13-EncryptedExtensions" + suffix,
13325				protocol: protocol,
13326				config: Config{
13327					MaxVersion: VersionTLS13,
13328				},
13329			},
13330		})
13331
13332		ret = append(ret, perMessageTest{
13333			messageType: typeCertificateRequest,
13334			test: testCase{
13335				name:     "TLS13-CertificateRequest" + suffix,
13336				protocol: protocol,
13337				config: Config{
13338					MaxVersion: VersionTLS13,
13339					ClientAuth: RequireAnyClientCert,
13340				},
13341			},
13342		})
13343
13344		ret = append(ret, perMessageTest{
13345			messageType: typeCertificate,
13346			test: testCase{
13347				name:     "TLS13-ServerCertificate" + suffix,
13348				protocol: protocol,
13349				config: Config{
13350					MaxVersion: VersionTLS13,
13351				},
13352			},
13353		})
13354
13355		ret = append(ret, perMessageTest{
13356			messageType: typeCertificateVerify,
13357			test: testCase{
13358				name:     "TLS13-ServerCertificateVerify" + suffix,
13359				protocol: protocol,
13360				config: Config{
13361					MaxVersion: VersionTLS13,
13362				},
13363			},
13364		})
13365
13366		ret = append(ret, perMessageTest{
13367			messageType: typeFinished,
13368			test: testCase{
13369				name:     "TLS13-ServerFinished" + suffix,
13370				protocol: protocol,
13371				config: Config{
13372					MaxVersion: VersionTLS13,
13373				},
13374			},
13375		})
13376
13377		ret = append(ret, perMessageTest{
13378			messageType: typeCertificate,
13379			test: testCase{
13380				testType: serverTest,
13381				protocol: protocol,
13382				name:     "TLS13-ClientCertificate" + suffix,
13383				config: Config{
13384					Credential: &rsaCertificate,
13385					MaxVersion: VersionTLS13,
13386				},
13387				flags: []string{"-require-any-client-certificate"},
13388			},
13389		})
13390
13391		ret = append(ret, perMessageTest{
13392			messageType: typeCertificateVerify,
13393			test: testCase{
13394				testType: serverTest,
13395				protocol: protocol,
13396				name:     "TLS13-ClientCertificateVerify" + suffix,
13397				config: Config{
13398					Credential: &rsaCertificate,
13399					MaxVersion: VersionTLS13,
13400				},
13401				flags: []string{"-require-any-client-certificate"},
13402			},
13403		})
13404
13405		ret = append(ret, perMessageTest{
13406			messageType: typeFinished,
13407			test: testCase{
13408				testType: serverTest,
13409				protocol: protocol,
13410				name:     "TLS13-ClientFinished" + suffix,
13411				config: Config{
13412					MaxVersion: VersionTLS13,
13413				},
13414			},
13415		})
13416
13417		// Only TLS uses EndOfEarlyData.
13418		if protocol == tls {
13419			ret = append(ret, perMessageTest{
13420				messageType: typeEndOfEarlyData,
13421				test: testCase{
13422					testType: serverTest,
13423					protocol: protocol,
13424					name:     "TLS13-EndOfEarlyData" + suffix,
13425					config: Config{
13426						MaxVersion: VersionTLS13,
13427					},
13428					resumeSession: true,
13429					earlyData:     true,
13430				},
13431			})
13432		}
13433	}
13434
13435	return ret
13436}
13437
13438func addWrongMessageTypeTests() {
13439	for _, t := range makePerMessageTests() {
13440		t.test.name = "WrongMessageType-" + t.test.name
13441		if t.test.resumeConfig != nil {
13442			t.test.resumeConfig.Bugs.SendWrongMessageType = t.messageType
13443		} else {
13444			t.test.config.Bugs.SendWrongMessageType = t.messageType
13445		}
13446		t.test.shouldFail = true
13447		t.test.expectedError = ":UNEXPECTED_MESSAGE:"
13448		t.test.expectedLocalError = "remote error: unexpected message"
13449
13450		if t.test.config.MaxVersion >= VersionTLS13 && t.messageType == typeServerHello {
13451			// In TLS 1.3, if the server believes it has sent ServerHello,
13452			// but the client cannot process it, the client will send an
13453			// unencrypted alert while the server expects encryption. In TLS,
13454			// this is a decryption failure. In QUIC, the encryption levels
13455			// do not match.
13456			if t.test.protocol == quic {
13457				t.test.expectedLocalError = "received record at initial encryption level, but expected handshake"
13458			} else {
13459				t.test.expectedLocalError = "local error: bad record MAC"
13460			}
13461		}
13462
13463		testCases = append(testCases, t.test)
13464	}
13465}
13466
13467func addTrailingMessageDataTests() {
13468	for _, t := range makePerMessageTests() {
13469		t.test.name = "TrailingMessageData-" + t.test.name
13470		if t.test.resumeConfig != nil {
13471			t.test.resumeConfig.Bugs.SendTrailingMessageData = t.messageType
13472		} else {
13473			t.test.config.Bugs.SendTrailingMessageData = t.messageType
13474		}
13475		t.test.shouldFail = true
13476		t.test.expectedError = ":DECODE_ERROR:"
13477		t.test.expectedLocalError = "remote error: error decoding message"
13478
13479		if t.test.config.MaxVersion >= VersionTLS13 && t.messageType == typeServerHello {
13480			// In TLS 1.3, if the server believes it has sent ServerHello,
13481			// but the client cannot process it, the client will send an
13482			// unencrypted alert while the server expects encryption. In TLS,
13483			// this is a decryption failure. In QUIC, the encryption levels
13484			// do not match.
13485			if t.test.protocol == quic {
13486				t.test.expectedLocalError = "received record at initial encryption level, but expected handshake"
13487			} else {
13488				t.test.expectedLocalError = "local error: bad record MAC"
13489			}
13490		}
13491
13492		if t.messageType == typeFinished {
13493			// Bad Finished messages read as the verify data having
13494			// the wrong length.
13495			t.test.expectedError = ":DIGEST_CHECK_FAILED:"
13496			t.test.expectedLocalError = "remote error: error decrypting message"
13497		}
13498
13499		testCases = append(testCases, t.test)
13500	}
13501}
13502
13503func addTLS13HandshakeTests() {
13504	testCases = append(testCases, testCase{
13505		testType: clientTest,
13506		name:     "NegotiatePSKResumption-TLS13",
13507		config: Config{
13508			MaxVersion: VersionTLS13,
13509			Bugs: ProtocolBugs{
13510				NegotiatePSKResumption: true,
13511			},
13512		},
13513		resumeSession: true,
13514		shouldFail:    true,
13515		expectedError: ":MISSING_KEY_SHARE:",
13516	})
13517
13518	testCases = append(testCases, testCase{
13519		testType: clientTest,
13520		name:     "MissingKeyShare-Client-TLS13",
13521		config: Config{
13522			MaxVersion: VersionTLS13,
13523			Bugs: ProtocolBugs{
13524				MissingKeyShare: true,
13525			},
13526		},
13527		shouldFail:    true,
13528		expectedError: ":MISSING_KEY_SHARE:",
13529	})
13530
13531	testCases = append(testCases, testCase{
13532		testType: serverTest,
13533		name:     "MissingKeyShare-Server-TLS13",
13534		config: Config{
13535			MaxVersion: VersionTLS13,
13536			Bugs: ProtocolBugs{
13537				MissingKeyShare: true,
13538			},
13539		},
13540		shouldFail:    true,
13541		expectedError: ":MISSING_KEY_SHARE:",
13542	})
13543
13544	testCases = append(testCases, testCase{
13545		testType: serverTest,
13546		name:     "DuplicateKeyShares-TLS13",
13547		config: Config{
13548			MaxVersion: VersionTLS13,
13549			Bugs: ProtocolBugs{
13550				DuplicateKeyShares: true,
13551			},
13552		},
13553		shouldFail:    true,
13554		expectedError: ":DUPLICATE_KEY_SHARE:",
13555	})
13556
13557	testCases = append(testCases, testCase{
13558		testType: serverTest,
13559		name:     "SkipEarlyData-TLS13",
13560		config: Config{
13561			MaxVersion: VersionTLS13,
13562			Bugs: ProtocolBugs{
13563				SendFakeEarlyDataLength: 4,
13564			},
13565		},
13566	})
13567
13568	// Test that enabling TLS 1.3 does not interfere with TLS 1.2 session ID
13569	// resumption.
13570	testCases = append(testCases, testCase{
13571		testType: clientTest,
13572		name:     "ResumeTLS12SessionID-TLS13",
13573		config: Config{
13574			MaxVersion:             VersionTLS12,
13575			SessionTicketsDisabled: true,
13576		},
13577		flags:         []string{"-max-version", strconv.Itoa(VersionTLS13)},
13578		resumeSession: true,
13579	})
13580
13581	// Test that the client correctly handles a TLS 1.3 ServerHello which echoes
13582	// a TLS 1.2 session ID.
13583	testCases = append(testCases, testCase{
13584		testType: clientTest,
13585		name:     "TLS12SessionID-TLS13",
13586		config: Config{
13587			MaxVersion:             VersionTLS12,
13588			SessionTicketsDisabled: true,
13589		},
13590		resumeConfig: &Config{
13591			MaxVersion: VersionTLS13,
13592		},
13593		resumeSession:        true,
13594		expectResumeRejected: true,
13595	})
13596
13597	// Test that the server correctly echoes back session IDs of
13598	// various lengths. The first test additionally asserts that
13599	// BoringSSL always sends the ChangeCipherSpec messages for
13600	// compatibility mode, rather than negotiating it based on the
13601	// ClientHello.
13602	testCases = append(testCases, testCase{
13603		testType: serverTest,
13604		name:     "EmptySessionID-TLS13",
13605		config: Config{
13606			MaxVersion: VersionTLS13,
13607			Bugs: ProtocolBugs{
13608				SendClientHelloSessionID: []byte{},
13609			},
13610		},
13611	})
13612
13613	testCases = append(testCases, testCase{
13614		testType: serverTest,
13615		name:     "Server-ShortSessionID-TLS13",
13616		config: Config{
13617			MaxVersion: VersionTLS13,
13618			Bugs: ProtocolBugs{
13619				SendClientHelloSessionID: make([]byte, 16),
13620			},
13621		},
13622	})
13623
13624	testCases = append(testCases, testCase{
13625		testType: serverTest,
13626		name:     "Server-FullSessionID-TLS13",
13627		config: Config{
13628			MaxVersion: VersionTLS13,
13629			Bugs: ProtocolBugs{
13630				SendClientHelloSessionID: make([]byte, 32),
13631			},
13632		},
13633	})
13634
13635	// The server should reject ClientHellos whose session IDs are too long.
13636	testCases = append(testCases, testCase{
13637		testType: serverTest,
13638		name:     "Server-TooLongSessionID-TLS13",
13639		config: Config{
13640			MaxVersion: VersionTLS13,
13641			Bugs: ProtocolBugs{
13642				SendClientHelloSessionID: make([]byte, 33),
13643			},
13644		},
13645		shouldFail:         true,
13646		expectedError:      ":DECODE_ERROR:",
13647		expectedLocalError: "remote error: error decoding message",
13648	})
13649	testCases = append(testCases, testCase{
13650		testType: serverTest,
13651		name:     "Server-TooLongSessionID-TLS12",
13652		config: Config{
13653			MaxVersion: VersionTLS12,
13654			Bugs: ProtocolBugs{
13655				SendClientHelloSessionID: make([]byte, 33),
13656			},
13657		},
13658		shouldFail:         true,
13659		expectedError:      ":DECODE_ERROR:",
13660		expectedLocalError: "remote error: error decoding message",
13661	})
13662
13663	// Test that the client correctly accepts or rejects short session IDs from
13664	// the server. Our tests use 32 bytes by default, so the boundary condition
13665	// is already covered.
13666	testCases = append(testCases, testCase{
13667		name: "Client-ShortSessionID",
13668		config: Config{
13669			MaxVersion:             VersionTLS12,
13670			SessionTicketsDisabled: true,
13671			Bugs: ProtocolBugs{
13672				NewSessionIDLength: 1,
13673			},
13674		},
13675		resumeSession: true,
13676	})
13677	testCases = append(testCases, testCase{
13678		name: "Client-TooLongSessionID",
13679		config: Config{
13680			MaxVersion:             VersionTLS12,
13681			SessionTicketsDisabled: true,
13682			Bugs: ProtocolBugs{
13683				NewSessionIDLength: 33,
13684			},
13685		},
13686		shouldFail:         true,
13687		expectedError:      ":DECODE_ERROR:",
13688		expectedLocalError: "remote error: error decoding message",
13689	})
13690
13691	// Test that the client sends a fake session ID in TLS 1.3. We cover both
13692	// normal and resumption handshakes to capture interactions with the
13693	// session resumption path.
13694	testCases = append(testCases, testCase{
13695		testType: clientTest,
13696		name:     "TLS13SessionID-TLS13",
13697		config: Config{
13698			MaxVersion: VersionTLS13,
13699			Bugs: ProtocolBugs{
13700				ExpectClientHelloSessionID: true,
13701			},
13702		},
13703		resumeSession: true,
13704	})
13705
13706	// Test that the client omits the fake session ID when the max version is TLS 1.2 and below.
13707	testCases = append(testCases, testCase{
13708		testType: clientTest,
13709		name:     "TLS12NoSessionID-TLS13",
13710		config: Config{
13711			MaxVersion: VersionTLS13,
13712			Bugs: ProtocolBugs{
13713				ExpectNoSessionID: true,
13714			},
13715		},
13716		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
13717	})
13718
13719	testCases = append(testCases, testCase{
13720		testType: clientTest,
13721		name:     "EarlyData-Client-TLS13",
13722		config: Config{
13723			MaxVersion: VersionTLS13,
13724			MinVersion: VersionTLS13,
13725		},
13726		resumeSession: true,
13727		earlyData:     true,
13728		flags: []string{
13729			"-on-initial-expect-early-data-reason", "no_session_offered",
13730			"-on-resume-expect-early-data-reason", "accept",
13731		},
13732	})
13733
13734	testCases = append(testCases, testCase{
13735		testType: clientTest,
13736		name:     "EarlyData-Reject-Client-TLS13",
13737		config: Config{
13738			MaxVersion: VersionTLS13,
13739		},
13740		resumeConfig: &Config{
13741			MaxVersion: VersionTLS13,
13742			Bugs: ProtocolBugs{
13743				AlwaysRejectEarlyData: true,
13744			},
13745		},
13746		resumeSession:           true,
13747		earlyData:               true,
13748		expectEarlyDataRejected: true,
13749		flags: []string{
13750			"-on-retry-expect-early-data-reason", "peer_declined",
13751		},
13752	})
13753
13754	testCases = append(testCases, testCase{
13755		testType: serverTest,
13756		name:     "EarlyData-Server-TLS13",
13757		config: Config{
13758			MaxVersion: VersionTLS13,
13759			MinVersion: VersionTLS13,
13760		},
13761		messageCount:  2,
13762		resumeSession: true,
13763		earlyData:     true,
13764		flags: []string{
13765			"-on-initial-expect-early-data-reason", "no_session_offered",
13766			"-on-resume-expect-early-data-reason", "accept",
13767		},
13768	})
13769
13770	// The above tests the most recent ticket. Additionally test that 0-RTT
13771	// works on the first ticket issued by the server.
13772	testCases = append(testCases, testCase{
13773		testType: serverTest,
13774		name:     "EarlyData-FirstTicket-Server-TLS13",
13775		config: Config{
13776			MaxVersion: VersionTLS13,
13777			MinVersion: VersionTLS13,
13778			Bugs: ProtocolBugs{
13779				UseFirstSessionTicket: true,
13780			},
13781		},
13782		messageCount:  2,
13783		resumeSession: true,
13784		earlyData:     true,
13785		flags: []string{
13786			"-on-resume-expect-early-data-reason", "accept",
13787		},
13788	})
13789
13790	testCases = append(testCases, testCase{
13791		testType: serverTest,
13792		name:     "SkipEarlyData-OmitEarlyDataExtension-TLS13",
13793		config: Config{
13794			MaxVersion: VersionTLS13,
13795			Bugs: ProtocolBugs{
13796				SendFakeEarlyDataLength: 4,
13797				OmitEarlyDataExtension:  true,
13798			},
13799		},
13800		shouldFail:    true,
13801		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
13802	})
13803
13804	testCases = append(testCases, testCase{
13805		testType: serverTest,
13806		name:     "SkipEarlyData-OmitEarlyDataExtension-HelloRetryRequest-TLS13",
13807		config: Config{
13808			MaxVersion: VersionTLS13,
13809			// Require a HelloRetryRequest for every curve.
13810			DefaultCurves: []CurveID{},
13811			Bugs: ProtocolBugs{
13812				SendFakeEarlyDataLength: 4,
13813				OmitEarlyDataExtension:  true,
13814			},
13815		},
13816		shouldFail:         true,
13817		expectedError:      ":UNEXPECTED_RECORD:",
13818		expectedLocalError: "remote error: unexpected message",
13819	})
13820
13821	testCases = append(testCases, testCase{
13822		testType: serverTest,
13823		name:     "SkipEarlyData-TooMuchData-TLS13",
13824		config: Config{
13825			MaxVersion: VersionTLS13,
13826			Bugs: ProtocolBugs{
13827				SendFakeEarlyDataLength: 16384 + 1,
13828			},
13829		},
13830		shouldFail:    true,
13831		expectedError: ":TOO_MUCH_SKIPPED_EARLY_DATA:",
13832	})
13833
13834	testCases = append(testCases, testCase{
13835		testType: serverTest,
13836		name:     "SkipEarlyData-Interleaved-TLS13",
13837		config: Config{
13838			MaxVersion: VersionTLS13,
13839			Bugs: ProtocolBugs{
13840				SendFakeEarlyDataLength: 4,
13841				InterleaveEarlyData:     true,
13842			},
13843		},
13844		shouldFail:    true,
13845		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
13846	})
13847
13848	testCases = append(testCases, testCase{
13849		testType: serverTest,
13850		name:     "SkipEarlyData-EarlyDataInTLS12-TLS13",
13851		config: Config{
13852			MaxVersion: VersionTLS13,
13853			Bugs: ProtocolBugs{
13854				SendFakeEarlyDataLength: 4,
13855			},
13856		},
13857		shouldFail:    true,
13858		expectedError: ":UNEXPECTED_RECORD:",
13859		flags:         []string{"-max-version", strconv.Itoa(VersionTLS12)},
13860	})
13861
13862	testCases = append(testCases, testCase{
13863		testType: serverTest,
13864		name:     "SkipEarlyData-HRR-TLS13",
13865		config: Config{
13866			MaxVersion: VersionTLS13,
13867			Bugs: ProtocolBugs{
13868				SendFakeEarlyDataLength: 4,
13869			},
13870			DefaultCurves: []CurveID{},
13871		},
13872		// Though the session is not resumed and we send HelloRetryRequest,
13873		// early data being disabled takes priority as the reject reason.
13874		flags: []string{"-expect-early-data-reason", "disabled"},
13875	})
13876
13877	testCases = append(testCases, testCase{
13878		testType: serverTest,
13879		name:     "SkipEarlyData-HRR-Interleaved-TLS13",
13880		config: Config{
13881			MaxVersion: VersionTLS13,
13882			Bugs: ProtocolBugs{
13883				SendFakeEarlyDataLength: 4,
13884				InterleaveEarlyData:     true,
13885			},
13886			DefaultCurves: []CurveID{},
13887		},
13888		shouldFail:    true,
13889		expectedError: ":UNEXPECTED_RECORD:",
13890	})
13891
13892	testCases = append(testCases, testCase{
13893		testType: serverTest,
13894		name:     "SkipEarlyData-HRR-TooMuchData-TLS13",
13895		config: Config{
13896			MaxVersion: VersionTLS13,
13897			Bugs: ProtocolBugs{
13898				SendFakeEarlyDataLength: 16384 + 1,
13899			},
13900			DefaultCurves: []CurveID{},
13901		},
13902		shouldFail:    true,
13903		expectedError: ":TOO_MUCH_SKIPPED_EARLY_DATA:",
13904	})
13905
13906	// Test that skipping early data looking for cleartext correctly
13907	// processes an alert record.
13908	testCases = append(testCases, testCase{
13909		testType: serverTest,
13910		name:     "SkipEarlyData-HRR-FatalAlert-TLS13",
13911		config: Config{
13912			MaxVersion: VersionTLS13,
13913			Bugs: ProtocolBugs{
13914				SendEarlyAlert:          true,
13915				SendFakeEarlyDataLength: 4,
13916			},
13917			DefaultCurves: []CurveID{},
13918		},
13919		shouldFail:    true,
13920		expectedError: ":SSLV3_ALERT_HANDSHAKE_FAILURE:",
13921	})
13922
13923	testCases = append(testCases, testCase{
13924		testType: serverTest,
13925		name:     "SkipEarlyData-SecondClientHelloEarlyData-TLS13",
13926		config: Config{
13927			MaxVersion: VersionTLS13,
13928			Bugs: ProtocolBugs{
13929				SendEarlyDataOnSecondClientHello: true,
13930			},
13931			DefaultCurves: []CurveID{},
13932		},
13933		shouldFail:         true,
13934		expectedLocalError: "remote error: bad record MAC",
13935	})
13936
13937	testCases = append(testCases, testCase{
13938		testType: clientTest,
13939		name:     "EmptyEncryptedExtensions-TLS13",
13940		config: Config{
13941			MaxVersion: VersionTLS13,
13942			Bugs: ProtocolBugs{
13943				EmptyEncryptedExtensions: true,
13944			},
13945		},
13946		shouldFail:         true,
13947		expectedLocalError: "remote error: error decoding message",
13948	})
13949
13950	testCases = append(testCases, testCase{
13951		testType: clientTest,
13952		name:     "EncryptedExtensionsWithKeyShare-TLS13",
13953		config: Config{
13954			MaxVersion: VersionTLS13,
13955			Bugs: ProtocolBugs{
13956				EncryptedExtensionsWithKeyShare: true,
13957			},
13958		},
13959		shouldFail:         true,
13960		expectedLocalError: "remote error: unsupported extension",
13961	})
13962
13963	testCases = append(testCases, testCase{
13964		testType: serverTest,
13965		name:     "SendHelloRetryRequest-TLS13",
13966		config: Config{
13967			MaxVersion: VersionTLS13,
13968			// Require a HelloRetryRequest for every curve.
13969			DefaultCurves:    []CurveID{},
13970			CurvePreferences: []CurveID{CurveX25519},
13971		},
13972		expectations: connectionExpectations{
13973			curveID: CurveX25519,
13974		},
13975		flags: []string{"-expect-hrr"},
13976	})
13977
13978	testCases = append(testCases, testCase{
13979		testType: serverTest,
13980		name:     "SendHelloRetryRequest-2-TLS13",
13981		config: Config{
13982			MaxVersion:       VersionTLS13,
13983			DefaultCurves:    []CurveID{CurveP384},
13984			CurvePreferences: []CurveID{CurveX25519, CurveP384},
13985		},
13986		// Although the ClientHello did not predict our preferred curve,
13987		// we always select it whether it is predicted or not.
13988		expectations: connectionExpectations{
13989			curveID: CurveX25519,
13990		},
13991		flags: []string{"-expect-hrr"},
13992	})
13993
13994	testCases = append(testCases, testCase{
13995		name: "UnknownCurve-HelloRetryRequest-TLS13",
13996		config: Config{
13997			MaxVersion: VersionTLS13,
13998			// P-384 requires HelloRetryRequest in BoringSSL.
13999			CurvePreferences: []CurveID{CurveP384},
14000			Bugs: ProtocolBugs{
14001				SendHelloRetryRequestCurve: bogusCurve,
14002			},
14003		},
14004		shouldFail:    true,
14005		expectedError: ":WRONG_CURVE:",
14006	})
14007
14008	testCases = append(testCases, testCase{
14009		name: "HelloRetryRequest-CipherChange-TLS13",
14010		config: Config{
14011			MaxVersion: VersionTLS13,
14012			// P-384 requires HelloRetryRequest in BoringSSL.
14013			CurvePreferences: []CurveID{CurveP384},
14014			Bugs: ProtocolBugs{
14015				SendCipherSuite:                  TLS_AES_128_GCM_SHA256,
14016				SendHelloRetryRequestCipherSuite: TLS_CHACHA20_POLY1305_SHA256,
14017			},
14018		},
14019		shouldFail:    true,
14020		expectedError: ":WRONG_CIPHER_RETURNED:",
14021	})
14022
14023	// Test that the client does not offer a PSK in the second ClientHello if the
14024	// HelloRetryRequest is incompatible with it.
14025	testCases = append(testCases, testCase{
14026		testType: clientTest,
14027		name:     "HelloRetryRequest-NonResumableCipher-TLS13",
14028		config: Config{
14029			MaxVersion: VersionTLS13,
14030			CipherSuites: []uint16{
14031				TLS_AES_128_GCM_SHA256,
14032			},
14033		},
14034		resumeConfig: &Config{
14035			MaxVersion: VersionTLS13,
14036			// P-384 requires HelloRetryRequest in BoringSSL.
14037			CurvePreferences: []CurveID{CurveP384},
14038			Bugs: ProtocolBugs{
14039				ExpectNoTLS13PSKAfterHRR: true,
14040			},
14041			CipherSuites: []uint16{
14042				TLS_AES_256_GCM_SHA384,
14043			},
14044		},
14045		resumeSession:        true,
14046		expectResumeRejected: true,
14047	})
14048
14049	testCases = append(testCases, testCase{
14050		name: "DisabledCurve-HelloRetryRequest-TLS13",
14051		config: Config{
14052			MaxVersion:       VersionTLS13,
14053			CurvePreferences: []CurveID{CurveP256},
14054			Bugs: ProtocolBugs{
14055				IgnorePeerCurvePreferences: true,
14056			},
14057		},
14058		flags:         []string{"-curves", strconv.Itoa(int(CurveP384))},
14059		shouldFail:    true,
14060		expectedError: ":WRONG_CURVE:",
14061	})
14062
14063	testCases = append(testCases, testCase{
14064		name: "UnnecessaryHelloRetryRequest-TLS13",
14065		config: Config{
14066			MaxVersion:       VersionTLS13,
14067			CurvePreferences: []CurveID{CurveX25519},
14068			Bugs: ProtocolBugs{
14069				SendHelloRetryRequestCurve: CurveX25519,
14070			},
14071		},
14072		shouldFail:    true,
14073		expectedError: ":WRONG_CURVE:",
14074	})
14075
14076	testCases = append(testCases, testCase{
14077		name: "SecondHelloRetryRequest-TLS13",
14078		config: Config{
14079			MaxVersion: VersionTLS13,
14080			// P-384 requires HelloRetryRequest in BoringSSL.
14081			CurvePreferences: []CurveID{CurveP384},
14082			Bugs: ProtocolBugs{
14083				SecondHelloRetryRequest: true,
14084			},
14085		},
14086		shouldFail:    true,
14087		expectedError: ":UNEXPECTED_MESSAGE:",
14088	})
14089
14090	testCases = append(testCases, testCase{
14091		name: "HelloRetryRequest-Empty-TLS13",
14092		config: Config{
14093			MaxVersion: VersionTLS13,
14094			Bugs: ProtocolBugs{
14095				AlwaysSendHelloRetryRequest: true,
14096			},
14097		},
14098		shouldFail:         true,
14099		expectedError:      ":EMPTY_HELLO_RETRY_REQUEST:",
14100		expectedLocalError: "remote error: illegal parameter",
14101	})
14102
14103	testCases = append(testCases, testCase{
14104		name: "HelloRetryRequest-DuplicateCurve-TLS13",
14105		config: Config{
14106			MaxVersion: VersionTLS13,
14107			// P-384 requires a HelloRetryRequest against BoringSSL's default
14108			// configuration. Assert this ExpectMissingKeyShare.
14109			CurvePreferences: []CurveID{CurveP384},
14110			Bugs: ProtocolBugs{
14111				ExpectMissingKeyShare:                true,
14112				DuplicateHelloRetryRequestExtensions: true,
14113			},
14114		},
14115		shouldFail:         true,
14116		expectedError:      ":DUPLICATE_EXTENSION:",
14117		expectedLocalError: "remote error: illegal parameter",
14118	})
14119
14120	testCases = append(testCases, testCase{
14121		name: "HelloRetryRequest-Cookie-TLS13",
14122		config: Config{
14123			MaxVersion: VersionTLS13,
14124			Bugs: ProtocolBugs{
14125				SendHelloRetryRequestCookie: []byte("cookie"),
14126			},
14127		},
14128	})
14129
14130	testCases = append(testCases, testCase{
14131		name: "HelloRetryRequest-DuplicateCookie-TLS13",
14132		config: Config{
14133			MaxVersion: VersionTLS13,
14134			Bugs: ProtocolBugs{
14135				SendHelloRetryRequestCookie:          []byte("cookie"),
14136				DuplicateHelloRetryRequestExtensions: true,
14137			},
14138		},
14139		shouldFail:         true,
14140		expectedError:      ":DUPLICATE_EXTENSION:",
14141		expectedLocalError: "remote error: illegal parameter",
14142	})
14143
14144	testCases = append(testCases, testCase{
14145		name: "HelloRetryRequest-EmptyCookie-TLS13",
14146		config: Config{
14147			MaxVersion: VersionTLS13,
14148			Bugs: ProtocolBugs{
14149				SendHelloRetryRequestCookie: []byte{},
14150			},
14151		},
14152		shouldFail:    true,
14153		expectedError: ":DECODE_ERROR:",
14154	})
14155
14156	testCases = append(testCases, testCase{
14157		name: "HelloRetryRequest-Cookie-Curve-TLS13",
14158		config: Config{
14159			MaxVersion: VersionTLS13,
14160			// P-384 requires HelloRetryRequest in BoringSSL.
14161			CurvePreferences: []CurveID{CurveP384},
14162			Bugs: ProtocolBugs{
14163				SendHelloRetryRequestCookie: []byte("cookie"),
14164				ExpectMissingKeyShare:       true,
14165			},
14166		},
14167	})
14168
14169	testCases = append(testCases, testCase{
14170		name: "HelloRetryRequest-Unknown-TLS13",
14171		config: Config{
14172			MaxVersion: VersionTLS13,
14173			Bugs: ProtocolBugs{
14174				CustomHelloRetryRequestExtension: "extension",
14175			},
14176		},
14177		shouldFail:         true,
14178		expectedError:      ":UNEXPECTED_EXTENSION:",
14179		expectedLocalError: "remote error: unsupported extension",
14180	})
14181
14182	testCases = append(testCases, testCase{
14183		testType: serverTest,
14184		name:     "SecondClientHelloMissingKeyShare-TLS13",
14185		config: Config{
14186			MaxVersion:    VersionTLS13,
14187			DefaultCurves: []CurveID{},
14188			Bugs: ProtocolBugs{
14189				SecondClientHelloMissingKeyShare: true,
14190			},
14191		},
14192		shouldFail:    true,
14193		expectedError: ":MISSING_KEY_SHARE:",
14194	})
14195
14196	testCases = append(testCases, testCase{
14197		testType: serverTest,
14198		name:     "SecondClientHelloWrongCurve-TLS13",
14199		config: Config{
14200			MaxVersion:    VersionTLS13,
14201			DefaultCurves: []CurveID{},
14202			Bugs: ProtocolBugs{
14203				MisinterpretHelloRetryRequestCurve: CurveP521,
14204			},
14205		},
14206		shouldFail:    true,
14207		expectedError: ":WRONG_CURVE:",
14208	})
14209
14210	testCases = append(testCases, testCase{
14211		name: "HelloRetryRequestVersionMismatch-TLS13",
14212		config: Config{
14213			MaxVersion: VersionTLS13,
14214			// P-384 requires HelloRetryRequest in BoringSSL.
14215			CurvePreferences: []CurveID{CurveP384},
14216			Bugs: ProtocolBugs{
14217				SendServerHelloVersion: 0x0305,
14218			},
14219		},
14220		shouldFail:    true,
14221		expectedError: ":DECODE_ERROR:",
14222	})
14223
14224	testCases = append(testCases, testCase{
14225		name: "HelloRetryRequestCurveMismatch-TLS13",
14226		config: Config{
14227			MaxVersion: VersionTLS13,
14228			// P-384 requires HelloRetryRequest in BoringSSL.
14229			CurvePreferences: []CurveID{CurveP384},
14230			Bugs: ProtocolBugs{
14231				// Send P-384 (correct) in the HelloRetryRequest.
14232				SendHelloRetryRequestCurve: CurveP384,
14233				// But send P-256 in the ServerHello.
14234				SendCurve: CurveP256,
14235			},
14236		},
14237		shouldFail:    true,
14238		expectedError: ":WRONG_CURVE:",
14239	})
14240
14241	// Test the server selecting a curve that requires a HelloRetryRequest
14242	// without sending it.
14243	testCases = append(testCases, testCase{
14244		name: "SkipHelloRetryRequest-TLS13",
14245		config: Config{
14246			MaxVersion: VersionTLS13,
14247			// P-384 requires HelloRetryRequest in BoringSSL.
14248			CurvePreferences: []CurveID{CurveP384},
14249			Bugs: ProtocolBugs{
14250				SkipHelloRetryRequest: true,
14251			},
14252		},
14253		shouldFail:    true,
14254		expectedError: ":WRONG_CURVE:",
14255	})
14256
14257	testCases = append(testCases, testCase{
14258		name: "SecondServerHelloNoVersion-TLS13",
14259		config: Config{
14260			MaxVersion: VersionTLS13,
14261			// P-384 requires HelloRetryRequest in BoringSSL.
14262			CurvePreferences: []CurveID{CurveP384},
14263			Bugs: ProtocolBugs{
14264				OmitServerSupportedVersionExtension: true,
14265			},
14266		},
14267		shouldFail:    true,
14268		expectedError: ":SECOND_SERVERHELLO_VERSION_MISMATCH:",
14269	})
14270	testCases = append(testCases, testCase{
14271		name: "SecondServerHelloWrongVersion-TLS13",
14272		config: Config{
14273			MaxVersion: VersionTLS13,
14274			// P-384 requires HelloRetryRequest in BoringSSL.
14275			CurvePreferences: []CurveID{CurveP384},
14276			Bugs: ProtocolBugs{
14277				SendServerSupportedVersionExtension: 0x1234,
14278			},
14279		},
14280		shouldFail:    true,
14281		expectedError: ":SECOND_SERVERHELLO_VERSION_MISMATCH:",
14282	})
14283
14284	testCases = append(testCases, testCase{
14285		name: "RequestContextInHandshake-TLS13",
14286		config: Config{
14287			MaxVersion: VersionTLS13,
14288			MinVersion: VersionTLS13,
14289			ClientAuth: RequireAnyClientCert,
14290			Bugs: ProtocolBugs{
14291				SendRequestContext: []byte("request context"),
14292			},
14293		},
14294		shimCertificate: &rsaCertificate,
14295		shouldFail:      true,
14296		expectedError:   ":DECODE_ERROR:",
14297	})
14298
14299	testCases = append(testCases, testCase{
14300		name: "UnknownExtensionInCertificateRequest-TLS13",
14301		config: Config{
14302			MaxVersion: VersionTLS13,
14303			MinVersion: VersionTLS13,
14304			ClientAuth: RequireAnyClientCert,
14305			Bugs: ProtocolBugs{
14306				SendCustomCertificateRequest: 0x1212,
14307			},
14308		},
14309		shimCertificate: &rsaCertificate,
14310	})
14311
14312	testCases = append(testCases, testCase{
14313		name: "MissingSignatureAlgorithmsInCertificateRequest-TLS13",
14314		config: Config{
14315			MaxVersion: VersionTLS13,
14316			MinVersion: VersionTLS13,
14317			ClientAuth: RequireAnyClientCert,
14318			Bugs: ProtocolBugs{
14319				OmitCertificateRequestAlgorithms: true,
14320			},
14321		},
14322		shimCertificate: &rsaCertificate,
14323		shouldFail:      true,
14324		expectedError:   ":DECODE_ERROR:",
14325	})
14326
14327	testCases = append(testCases, testCase{
14328		testType: serverTest,
14329		name:     "TrailingKeyShareData-TLS13",
14330		config: Config{
14331			MaxVersion: VersionTLS13,
14332			Bugs: ProtocolBugs{
14333				TrailingKeyShareData: true,
14334			},
14335		},
14336		shouldFail:    true,
14337		expectedError: ":DECODE_ERROR:",
14338	})
14339
14340	testCases = append(testCases, testCase{
14341		name: "AlwaysSelectPSKIdentity-TLS13",
14342		config: Config{
14343			MaxVersion: VersionTLS13,
14344			Bugs: ProtocolBugs{
14345				AlwaysSelectPSKIdentity: true,
14346			},
14347		},
14348		shouldFail:    true,
14349		expectedError: ":UNEXPECTED_EXTENSION:",
14350	})
14351
14352	testCases = append(testCases, testCase{
14353		name: "InvalidPSKIdentity-TLS13",
14354		config: Config{
14355			MaxVersion: VersionTLS13,
14356			Bugs: ProtocolBugs{
14357				SelectPSKIdentityOnResume: 1,
14358			},
14359		},
14360		resumeSession: true,
14361		shouldFail:    true,
14362		expectedError: ":PSK_IDENTITY_NOT_FOUND:",
14363	})
14364
14365	testCases = append(testCases, testCase{
14366		testType: serverTest,
14367		name:     "ExtraPSKIdentity-TLS13",
14368		config: Config{
14369			MaxVersion: VersionTLS13,
14370			Bugs: ProtocolBugs{
14371				ExtraPSKIdentity:   true,
14372				SendExtraPSKBinder: true,
14373			},
14374		},
14375		resumeSession: true,
14376	})
14377
14378	// Test that unknown NewSessionTicket extensions are tolerated.
14379	testCases = append(testCases, testCase{
14380		name: "CustomTicketExtension-TLS13",
14381		config: Config{
14382			MaxVersion: VersionTLS13,
14383			Bugs: ProtocolBugs{
14384				CustomTicketExtension: "1234",
14385			},
14386		},
14387	})
14388
14389	// Test the client handles 0-RTT being rejected by a full handshake
14390	// and correctly reports a certificate change.
14391	testCases = append(testCases, testCase{
14392		testType: clientTest,
14393		name:     "EarlyData-RejectTicket-Client-TLS13",
14394		config: Config{
14395			MaxVersion: VersionTLS13,
14396			Credential: &rsaCertificate,
14397		},
14398		resumeConfig: &Config{
14399			MaxVersion:             VersionTLS13,
14400			Credential:             &ecdsaP256Certificate,
14401			SessionTicketsDisabled: true,
14402		},
14403		resumeSession:           true,
14404		expectResumeRejected:    true,
14405		earlyData:               true,
14406		expectEarlyDataRejected: true,
14407		flags: []string{
14408			"-on-retry-expect-early-data-reason", "session_not_resumed",
14409			// Test the peer certificate is reported correctly in each of the
14410			// three logical connections.
14411			"-on-initial-expect-peer-cert-file", rsaCertificate.ChainPath,
14412			"-on-resume-expect-peer-cert-file", rsaCertificate.ChainPath,
14413			"-on-retry-expect-peer-cert-file", ecdsaP256Certificate.ChainPath,
14414			// Session tickets are disabled, so the runner will not send a ticket.
14415			"-on-retry-expect-no-session",
14416		},
14417	})
14418
14419	// Test the server rejects 0-RTT if it does not recognize the ticket.
14420	testCases = append(testCases, testCase{
14421		testType: serverTest,
14422		name:     "EarlyData-RejectTicket-Server-TLS13",
14423		config: Config{
14424			MaxVersion: VersionTLS13,
14425			MinVersion: VersionTLS13,
14426			Bugs: ProtocolBugs{
14427				// Corrupt the ticket.
14428				FilterTicket: func(in []byte) ([]byte, error) {
14429					in[len(in)-1] ^= 1
14430					return in, nil
14431				},
14432			},
14433		},
14434		messageCount:            2,
14435		resumeSession:           true,
14436		expectResumeRejected:    true,
14437		earlyData:               true,
14438		expectEarlyDataRejected: true,
14439		flags: []string{
14440			"-on-resume-expect-early-data-reason", "session_not_resumed",
14441		},
14442	})
14443
14444	// Test the client handles 0-RTT being rejected via a HelloRetryRequest.
14445	testCases = append(testCases, testCase{
14446		testType: clientTest,
14447		name:     "EarlyData-HRR-Client-TLS13",
14448		config: Config{
14449			MaxVersion: VersionTLS13,
14450		},
14451		resumeConfig: &Config{
14452			MaxVersion: VersionTLS13,
14453			Bugs: ProtocolBugs{
14454				SendHelloRetryRequestCookie: []byte{1, 2, 3, 4},
14455			},
14456		},
14457		resumeSession:           true,
14458		earlyData:               true,
14459		expectEarlyDataRejected: true,
14460		flags: []string{
14461			"-on-retry-expect-early-data-reason", "hello_retry_request",
14462		},
14463	})
14464
14465	// Test the server rejects 0-RTT if it needs to send a HelloRetryRequest.
14466	testCases = append(testCases, testCase{
14467		testType: serverTest,
14468		name:     "EarlyData-HRR-Server-TLS13",
14469		config: Config{
14470			MaxVersion: VersionTLS13,
14471			MinVersion: VersionTLS13,
14472			// Require a HelloRetryRequest for every curve.
14473			DefaultCurves: []CurveID{},
14474		},
14475		messageCount:            2,
14476		resumeSession:           true,
14477		earlyData:               true,
14478		expectEarlyDataRejected: true,
14479		flags: []string{
14480			"-on-resume-expect-early-data-reason", "hello_retry_request",
14481		},
14482	})
14483
14484	// Test the client handles a 0-RTT reject from both ticket rejection and
14485	// HelloRetryRequest.
14486	testCases = append(testCases, testCase{
14487		testType: clientTest,
14488		name:     "EarlyData-HRR-RejectTicket-Client-TLS13",
14489		config: Config{
14490			MaxVersion: VersionTLS13,
14491			Credential: &rsaCertificate,
14492		},
14493		resumeConfig: &Config{
14494			MaxVersion:             VersionTLS13,
14495			Credential:             &ecdsaP256Certificate,
14496			SessionTicketsDisabled: true,
14497			Bugs: ProtocolBugs{
14498				SendHelloRetryRequestCookie: []byte{1, 2, 3, 4},
14499			},
14500		},
14501		resumeSession:           true,
14502		expectResumeRejected:    true,
14503		earlyData:               true,
14504		expectEarlyDataRejected: true,
14505		flags: []string{
14506			// The client sees HelloRetryRequest before the resumption result,
14507			// though neither value is inherently preferable.
14508			"-on-retry-expect-early-data-reason", "hello_retry_request",
14509			// Test the peer certificate is reported correctly in each of the
14510			// three logical connections.
14511			"-on-initial-expect-peer-cert-file", rsaCertificate.ChainPath,
14512			"-on-resume-expect-peer-cert-file", rsaCertificate.ChainPath,
14513			"-on-retry-expect-peer-cert-file", ecdsaP256Certificate.ChainPath,
14514			// Session tickets are disabled, so the runner will not send a ticket.
14515			"-on-retry-expect-no-session",
14516		},
14517	})
14518
14519	// Test the server rejects 0-RTT if it needs to send a HelloRetryRequest.
14520	testCases = append(testCases, testCase{
14521		testType: serverTest,
14522		name:     "EarlyData-HRR-RejectTicket-Server-TLS13",
14523		config: Config{
14524			MaxVersion: VersionTLS13,
14525			MinVersion: VersionTLS13,
14526			// Require a HelloRetryRequest for every curve.
14527			DefaultCurves: []CurveID{},
14528			Bugs: ProtocolBugs{
14529				// Corrupt the ticket.
14530				FilterTicket: func(in []byte) ([]byte, error) {
14531					in[len(in)-1] ^= 1
14532					return in, nil
14533				},
14534			},
14535		},
14536		messageCount:            2,
14537		resumeSession:           true,
14538		expectResumeRejected:    true,
14539		earlyData:               true,
14540		expectEarlyDataRejected: true,
14541		flags: []string{
14542			// The server sees the missed resumption before HelloRetryRequest,
14543			// though neither value is inherently preferable.
14544			"-on-resume-expect-early-data-reason", "session_not_resumed",
14545		},
14546	})
14547
14548	// The client must check the server does not send the early_data
14549	// extension while rejecting the session.
14550	testCases = append(testCases, testCase{
14551		testType: clientTest,
14552		name:     "EarlyDataWithoutResume-Client-TLS13",
14553		config: Config{
14554			MaxVersion:       VersionTLS13,
14555			MaxEarlyDataSize: 16384,
14556		},
14557		resumeConfig: &Config{
14558			MaxVersion:             VersionTLS13,
14559			SessionTicketsDisabled: true,
14560			Bugs: ProtocolBugs{
14561				SendEarlyDataExtension: true,
14562			},
14563		},
14564		resumeSession: true,
14565		earlyData:     true,
14566		shouldFail:    true,
14567		expectedError: ":UNEXPECTED_EXTENSION:",
14568	})
14569
14570	// The client must fail with a dedicated error code if the server
14571	// responds with TLS 1.2 when offering 0-RTT.
14572	testCases = append(testCases, testCase{
14573		testType: clientTest,
14574		name:     "EarlyDataVersionDowngrade-Client-TLS13",
14575		config: Config{
14576			MaxVersion: VersionTLS13,
14577		},
14578		resumeConfig: &Config{
14579			MaxVersion: VersionTLS12,
14580		},
14581		resumeSession: true,
14582		earlyData:     true,
14583		shouldFail:    true,
14584		expectedError: ":WRONG_VERSION_ON_EARLY_DATA:",
14585	})
14586
14587	// Test that the client rejects an (unsolicited) early_data extension if
14588	// the server sent an HRR.
14589	testCases = append(testCases, testCase{
14590		testType: clientTest,
14591		name:     "ServerAcceptsEarlyDataOnHRR-Client-TLS13",
14592		config: Config{
14593			MaxVersion: VersionTLS13,
14594		},
14595		resumeConfig: &Config{
14596			MaxVersion: VersionTLS13,
14597			Bugs: ProtocolBugs{
14598				SendHelloRetryRequestCookie: []byte{1, 2, 3, 4},
14599				SendEarlyDataExtension:      true,
14600			},
14601		},
14602		resumeSession: true,
14603		earlyData:     true,
14604		// The client will first process an early data reject from the HRR.
14605		expectEarlyDataRejected: true,
14606		shouldFail:              true,
14607		expectedError:           ":UNEXPECTED_EXTENSION:",
14608	})
14609
14610	testCases = append(testCases, testCase{
14611		testType: clientTest,
14612		name:     "SkipChangeCipherSpec-Client-TLS13",
14613		config: Config{
14614			MaxVersion: VersionTLS13,
14615			Bugs: ProtocolBugs{
14616				SkipChangeCipherSpec: true,
14617			},
14618		},
14619	})
14620
14621	testCases = append(testCases, testCase{
14622		testType: serverTest,
14623		name:     "SkipChangeCipherSpec-Server-TLS13",
14624		config: Config{
14625			MaxVersion: VersionTLS13,
14626			Bugs: ProtocolBugs{
14627				SkipChangeCipherSpec: true,
14628			},
14629		},
14630	})
14631
14632	testCases = append(testCases, testCase{
14633		testType: clientTest,
14634		name:     "TooManyChangeCipherSpec-Client-TLS13",
14635		config: Config{
14636			MaxVersion: VersionTLS13,
14637			Bugs: ProtocolBugs{
14638				SendExtraChangeCipherSpec: 33,
14639			},
14640		},
14641		shouldFail:    true,
14642		expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
14643	})
14644
14645	testCases = append(testCases, testCase{
14646		testType: serverTest,
14647		name:     "TooManyChangeCipherSpec-Server-TLS13",
14648		config: Config{
14649			MaxVersion: VersionTLS13,
14650			Bugs: ProtocolBugs{
14651				SendExtraChangeCipherSpec: 33,
14652			},
14653		},
14654		shouldFail:    true,
14655		expectedError: ":TOO_MANY_EMPTY_FRAGMENTS:",
14656	})
14657
14658	testCases = append(testCases, testCase{
14659		name: "SendPostHandshakeChangeCipherSpec-TLS13",
14660		config: Config{
14661			MaxVersion: VersionTLS13,
14662			Bugs: ProtocolBugs{
14663				SendPostHandshakeChangeCipherSpec: true,
14664			},
14665		},
14666		shouldFail:         true,
14667		expectedError:      ":UNEXPECTED_RECORD:",
14668		expectedLocalError: "remote error: unexpected message",
14669	})
14670
14671	fooString := "foo"
14672	barString := "bar"
14673
14674	// Test that the client reports the correct ALPN after a 0-RTT reject
14675	// that changed it.
14676	testCases = append(testCases, testCase{
14677		testType: clientTest,
14678		name:     "EarlyData-ALPNMismatch-Client-TLS13",
14679		config: Config{
14680			MaxVersion: VersionTLS13,
14681			Bugs: ProtocolBugs{
14682				ALPNProtocol: &fooString,
14683			},
14684		},
14685		resumeConfig: &Config{
14686			MaxVersion: VersionTLS13,
14687			Bugs: ProtocolBugs{
14688				ALPNProtocol: &barString,
14689			},
14690		},
14691		resumeSession:           true,
14692		earlyData:               true,
14693		expectEarlyDataRejected: true,
14694		flags: []string{
14695			"-advertise-alpn", "\x03foo\x03bar",
14696			// The client does not learn ALPN was the cause.
14697			"-on-retry-expect-early-data-reason", "peer_declined",
14698			// In the 0-RTT state, we surface the predicted ALPN. After
14699			// processing the reject, we surface the real one.
14700			"-on-initial-expect-alpn", "foo",
14701			"-on-resume-expect-alpn", "foo",
14702			"-on-retry-expect-alpn", "bar",
14703		},
14704	})
14705
14706	// Test that the client reports the correct ALPN after a 0-RTT reject if
14707	// ALPN was omitted from the first connection.
14708	testCases = append(testCases, testCase{
14709		testType: clientTest,
14710		name:     "EarlyData-ALPNOmitted1-Client-TLS13",
14711		config: Config{
14712			MaxVersion: VersionTLS13,
14713		},
14714		resumeConfig: &Config{
14715			MaxVersion: VersionTLS13,
14716			NextProtos: []string{"foo"},
14717		},
14718		resumeSession:           true,
14719		earlyData:               true,
14720		expectEarlyDataRejected: true,
14721		flags: []string{
14722			"-advertise-alpn", "\x03foo\x03bar",
14723			// The client does not learn ALPN was the cause.
14724			"-on-retry-expect-early-data-reason", "peer_declined",
14725			// In the 0-RTT state, we surface the predicted ALPN. After
14726			// processing the reject, we surface the real one.
14727			"-on-initial-expect-alpn", "",
14728			"-on-resume-expect-alpn", "",
14729			"-on-retry-expect-alpn", "foo",
14730		},
14731	})
14732
14733	// Test that the client reports the correct ALPN after a 0-RTT reject if
14734	// ALPN was omitted from the second connection.
14735	testCases = append(testCases, testCase{
14736		testType: clientTest,
14737		name:     "EarlyData-ALPNOmitted2-Client-TLS13",
14738		config: Config{
14739			MaxVersion: VersionTLS13,
14740			NextProtos: []string{"foo"},
14741		},
14742		resumeConfig: &Config{
14743			MaxVersion: VersionTLS13,
14744		},
14745		resumeSession:           true,
14746		earlyData:               true,
14747		expectEarlyDataRejected: true,
14748		flags: []string{
14749			"-advertise-alpn", "\x03foo\x03bar",
14750			// The client does not learn ALPN was the cause.
14751			"-on-retry-expect-early-data-reason", "peer_declined",
14752			// In the 0-RTT state, we surface the predicted ALPN. After
14753			// processing the reject, we surface the real one.
14754			"-on-initial-expect-alpn", "foo",
14755			"-on-resume-expect-alpn", "foo",
14756			"-on-retry-expect-alpn", "",
14757		},
14758	})
14759
14760	// Test that the client enforces ALPN match on 0-RTT accept.
14761	testCases = append(testCases, testCase{
14762		testType: clientTest,
14763		name:     "EarlyData-BadALPNMismatch-Client-TLS13",
14764		config: Config{
14765			MaxVersion: VersionTLS13,
14766			Bugs: ProtocolBugs{
14767				ALPNProtocol: &fooString,
14768			},
14769		},
14770		resumeConfig: &Config{
14771			MaxVersion: VersionTLS13,
14772			Bugs: ProtocolBugs{
14773				AlwaysAcceptEarlyData: true,
14774				ALPNProtocol:          &barString,
14775			},
14776		},
14777		resumeSession: true,
14778		earlyData:     true,
14779		flags: []string{
14780			"-advertise-alpn", "\x03foo\x03bar",
14781			"-on-initial-expect-alpn", "foo",
14782			"-on-resume-expect-alpn", "foo",
14783			"-on-retry-expect-alpn", "bar",
14784		},
14785		shouldFail:         true,
14786		expectedError:      ":ALPN_MISMATCH_ON_EARLY_DATA:",
14787		expectedLocalError: "remote error: illegal parameter",
14788	})
14789
14790	// Test that the client does not offer early data if it is incompatible
14791	// with ALPN preferences.
14792	testCases = append(testCases, testCase{
14793		testType: clientTest,
14794		name:     "EarlyData-ALPNPreferenceChanged-TLS13",
14795		config: Config{
14796			MaxVersion:       VersionTLS13,
14797			MaxEarlyDataSize: 16384,
14798			NextProtos:       []string{"foo", "bar"},
14799		},
14800		resumeSession: true,
14801		flags: []string{
14802			"-enable-early-data",
14803			"-expect-ticket-supports-early-data",
14804			"-expect-no-offer-early-data",
14805			// Offer different ALPN values in the initial and resumption.
14806			"-on-initial-advertise-alpn", "\x03foo",
14807			"-on-initial-expect-alpn", "foo",
14808			"-on-resume-advertise-alpn", "\x03bar",
14809			"-on-resume-expect-alpn", "bar",
14810			// The ALPN mismatch comes from the client, so it reports it as the
14811			// reason.
14812			"-on-resume-expect-early-data-reason", "alpn_mismatch",
14813		},
14814	})
14815
14816	// Test that the client does not offer 0-RTT to servers which never
14817	// advertise it.
14818	testCases = append(testCases, testCase{
14819		testType: clientTest,
14820		name:     "EarlyData-NonZeroRTTSession-Client-TLS13",
14821		config: Config{
14822			MaxVersion: VersionTLS13,
14823		},
14824		resumeSession: true,
14825		flags: []string{
14826			"-enable-early-data",
14827			"-on-resume-expect-no-offer-early-data",
14828			// The client declines to offer 0-RTT because of the session.
14829			"-on-resume-expect-early-data-reason", "unsupported_for_session",
14830		},
14831	})
14832
14833	// Test that the server correctly rejects 0-RTT when the previous
14834	// session did not allow early data on resumption.
14835	testCases = append(testCases, testCase{
14836		testType: serverTest,
14837		name:     "EarlyData-NonZeroRTTSession-Server-TLS13",
14838		config: Config{
14839			MaxVersion: VersionTLS13,
14840		},
14841		resumeConfig: &Config{
14842			MaxVersion: VersionTLS13,
14843			Bugs: ProtocolBugs{
14844				SendEarlyData:           [][]byte{{1, 2, 3, 4}},
14845				ExpectEarlyDataAccepted: false,
14846			},
14847		},
14848		resumeSession: true,
14849		// This test configures early data manually instead of the earlyData
14850		// option, to customize the -enable-early-data flag.
14851		flags: []string{
14852			"-on-resume-enable-early-data",
14853			"-expect-reject-early-data",
14854			// The server rejects 0-RTT because of the session.
14855			"-on-resume-expect-early-data-reason", "unsupported_for_session",
14856		},
14857	})
14858
14859	// Test that we reject early data where ALPN is omitted from the first
14860	// connection, but negotiated in the second.
14861	testCases = append(testCases, testCase{
14862		testType: serverTest,
14863		name:     "EarlyData-ALPNOmitted1-Server-TLS13",
14864		config: Config{
14865			MaxVersion: VersionTLS13,
14866			NextProtos: []string{},
14867		},
14868		resumeConfig: &Config{
14869			MaxVersion: VersionTLS13,
14870			NextProtos: []string{"foo"},
14871		},
14872		resumeSession:           true,
14873		earlyData:               true,
14874		expectEarlyDataRejected: true,
14875		flags: []string{
14876			"-on-initial-select-alpn", "",
14877			"-on-resume-select-alpn", "foo",
14878			"-on-resume-expect-early-data-reason", "alpn_mismatch",
14879		},
14880	})
14881
14882	// Test that we reject early data where ALPN is omitted from the second
14883	// connection, but negotiated in the first.
14884	testCases = append(testCases, testCase{
14885		testType: serverTest,
14886		name:     "EarlyData-ALPNOmitted2-Server-TLS13",
14887		config: Config{
14888			MaxVersion: VersionTLS13,
14889			NextProtos: []string{"foo"},
14890		},
14891		resumeConfig: &Config{
14892			MaxVersion: VersionTLS13,
14893			NextProtos: []string{},
14894		},
14895		resumeSession:           true,
14896		earlyData:               true,
14897		expectEarlyDataRejected: true,
14898		flags: []string{
14899			"-on-initial-select-alpn", "foo",
14900			"-on-resume-select-alpn", "",
14901			"-on-resume-expect-early-data-reason", "alpn_mismatch",
14902		},
14903	})
14904
14905	// Test that we reject early data with mismatched ALPN.
14906	testCases = append(testCases, testCase{
14907		testType: serverTest,
14908		name:     "EarlyData-ALPNMismatch-Server-TLS13",
14909		config: Config{
14910			MaxVersion: VersionTLS13,
14911			NextProtos: []string{"foo"},
14912		},
14913		resumeConfig: &Config{
14914			MaxVersion: VersionTLS13,
14915			NextProtos: []string{"bar"},
14916		},
14917		resumeSession:           true,
14918		earlyData:               true,
14919		expectEarlyDataRejected: true,
14920		flags: []string{
14921			"-on-initial-select-alpn", "foo",
14922			"-on-resume-select-alpn", "bar",
14923			"-on-resume-expect-early-data-reason", "alpn_mismatch",
14924		},
14925	})
14926
14927	// Test that the client offering 0-RTT and Channel ID forbids the server
14928	// from accepting both.
14929	testCases = append(testCases, testCase{
14930		testType: clientTest,
14931		name:     "EarlyDataChannelID-AcceptBoth-Client-TLS13",
14932		config: Config{
14933			MaxVersion:       VersionTLS13,
14934			RequestChannelID: true,
14935		},
14936		resumeSession: true,
14937		earlyData:     true,
14938		expectations: connectionExpectations{
14939			channelID: true,
14940		},
14941		shouldFail:         true,
14942		expectedError:      ":UNEXPECTED_EXTENSION_ON_EARLY_DATA:",
14943		expectedLocalError: "remote error: illegal parameter",
14944		flags: []string{
14945			"-send-channel-id", channelIDKeyPath,
14946		},
14947	})
14948
14949	// Test that the client offering Channel ID and 0-RTT allows the server
14950	// to decline 0-RTT.
14951	testCases = append(testCases, testCase{
14952		testType: clientTest,
14953		name:     "EarlyDataChannelID-AcceptChannelID-Client-TLS13",
14954		config: Config{
14955			MaxVersion:       VersionTLS13,
14956			RequestChannelID: true,
14957			Bugs: ProtocolBugs{
14958				AlwaysRejectEarlyData: true,
14959			},
14960		},
14961		resumeSession:           true,
14962		earlyData:               true,
14963		expectEarlyDataRejected: true,
14964		expectations: connectionExpectations{
14965			channelID: true,
14966		},
14967		flags: []string{
14968			"-send-channel-id", channelIDKeyPath,
14969			// The client never learns the reason was Channel ID.
14970			"-on-retry-expect-early-data-reason", "peer_declined",
14971		},
14972	})
14973
14974	// Test that the client offering Channel ID and 0-RTT allows the server
14975	// to decline Channel ID.
14976	testCases = append(testCases, testCase{
14977		testType: clientTest,
14978		name:     "EarlyDataChannelID-AcceptEarlyData-Client-TLS13",
14979		config: Config{
14980			MaxVersion: VersionTLS13,
14981		},
14982		resumeSession: true,
14983		earlyData:     true,
14984		flags: []string{
14985			"-send-channel-id", channelIDKeyPath,
14986		},
14987	})
14988
14989	// Test that the server supporting Channel ID and 0-RTT declines 0-RTT
14990	// if it would negotiate Channel ID.
14991	testCases = append(testCases, testCase{
14992		testType: serverTest,
14993		name:     "EarlyDataChannelID-OfferBoth-Server-TLS13",
14994		config: Config{
14995			MaxVersion: VersionTLS13,
14996			ChannelID:  &channelIDKey,
14997		},
14998		resumeSession:           true,
14999		earlyData:               true,
15000		expectEarlyDataRejected: true,
15001		expectations: connectionExpectations{
15002			channelID: true,
15003		},
15004		flags: []string{
15005			"-expect-channel-id",
15006			base64FlagValue(channelIDBytes),
15007			"-on-resume-expect-early-data-reason", "channel_id",
15008		},
15009	})
15010
15011	// Test that the server supporting Channel ID and 0-RTT accepts 0-RTT
15012	// if not offered Channel ID.
15013	testCases = append(testCases, testCase{
15014		testType: serverTest,
15015		name:     "EarlyDataChannelID-OfferEarlyData-Server-TLS13",
15016		config: Config{
15017			MaxVersion: VersionTLS13,
15018		},
15019		resumeSession: true,
15020		earlyData:     true,
15021		expectations: connectionExpectations{
15022			channelID: false,
15023		},
15024		flags: []string{
15025			"-enable-channel-id",
15026			"-on-resume-expect-early-data-reason", "accept",
15027		},
15028	})
15029
15030	// Test that the server errors on 0-RTT streams without end_of_early_data.
15031	// The subsequent records should fail to decrypt.
15032	testCases = append(testCases, testCase{
15033		testType: serverTest,
15034		name:     "EarlyData-SkipEndOfEarlyData-TLS13",
15035		config: Config{
15036			MaxVersion: VersionTLS13,
15037			Bugs: ProtocolBugs{
15038				SkipEndOfEarlyData: true,
15039			},
15040		},
15041		resumeSession:      true,
15042		earlyData:          true,
15043		shouldFail:         true,
15044		expectedLocalError: "remote error: bad record MAC",
15045		expectedError:      ":BAD_DECRYPT:",
15046	})
15047
15048	// Test that the server errors on 0-RTT streams with a stray handshake
15049	// message in them.
15050	testCases = append(testCases, testCase{
15051		testType: serverTest,
15052		name:     "EarlyData-UnexpectedHandshake-Server-TLS13",
15053		config: Config{
15054			MaxVersion: VersionTLS13,
15055		},
15056		resumeConfig: &Config{
15057			MaxVersion: VersionTLS13,
15058			Bugs: ProtocolBugs{
15059				SendStrayEarlyHandshake: true,
15060			},
15061		},
15062		resumeSession:      true,
15063		earlyData:          true,
15064		shouldFail:         true,
15065		expectedError:      ":UNEXPECTED_MESSAGE:",
15066		expectedLocalError: "remote error: unexpected message",
15067	})
15068
15069	// Test that the client reports TLS 1.3 as the version while sending
15070	// early data.
15071	testCases = append(testCases, testCase{
15072		testType: clientTest,
15073		name:     "EarlyData-Client-VersionAPI-TLS13",
15074		config: Config{
15075			MaxVersion: VersionTLS13,
15076		},
15077		resumeSession: true,
15078		earlyData:     true,
15079		flags: []string{
15080			"-expect-version", strconv.Itoa(VersionTLS13),
15081		},
15082	})
15083
15084	// Test that client and server both notice handshake errors after data
15085	// has started flowing.
15086	testCases = append(testCases, testCase{
15087		testType: clientTest,
15088		name:     "EarlyData-Client-BadFinished-TLS13",
15089		config: Config{
15090			MaxVersion: VersionTLS13,
15091		},
15092		resumeConfig: &Config{
15093			MaxVersion: VersionTLS13,
15094			Bugs: ProtocolBugs{
15095				BadFinished: true,
15096			},
15097		},
15098		resumeSession:      true,
15099		earlyData:          true,
15100		shouldFail:         true,
15101		expectedError:      ":DIGEST_CHECK_FAILED:",
15102		expectedLocalError: "remote error: error decrypting message",
15103	})
15104	testCases = append(testCases, testCase{
15105		testType: serverTest,
15106		name:     "EarlyData-Server-BadFinished-TLS13",
15107		config: Config{
15108			MaxVersion: VersionTLS13,
15109		},
15110		resumeConfig: &Config{
15111			MaxVersion: VersionTLS13,
15112			Bugs: ProtocolBugs{
15113				BadFinished: true,
15114			},
15115		},
15116		resumeSession:      true,
15117		earlyData:          true,
15118		shouldFail:         true,
15119		expectedError:      ":DIGEST_CHECK_FAILED:",
15120		expectedLocalError: "remote error: error decrypting message",
15121	})
15122
15123	testCases = append(testCases, testCase{
15124		testType: serverTest,
15125		name:     "Server-NonEmptyEndOfEarlyData-TLS13",
15126		config: Config{
15127			MaxVersion: VersionTLS13,
15128		},
15129		resumeConfig: &Config{
15130			MaxVersion: VersionTLS13,
15131			Bugs: ProtocolBugs{
15132				NonEmptyEndOfEarlyData: true,
15133			},
15134		},
15135		resumeSession: true,
15136		earlyData:     true,
15137		shouldFail:    true,
15138		expectedError: ":DECODE_ERROR:",
15139	})
15140
15141	testCases = append(testCases, testCase{
15142		testType: serverTest,
15143		name:     "ServerSkipCertificateVerify-TLS13",
15144		config: Config{
15145			MinVersion: VersionTLS13,
15146			MaxVersion: VersionTLS13,
15147			Credential: &rsaChainCertificate,
15148			Bugs: ProtocolBugs{
15149				SkipCertificateVerify: true,
15150			},
15151		},
15152		expectations: connectionExpectations{
15153			peerCertificate: &rsaCertificate,
15154		},
15155		shimCertificate: &rsaCertificate,
15156		flags: []string{
15157			"-require-any-client-certificate",
15158		},
15159		shouldFail:         true,
15160		expectedError:      ":UNEXPECTED_MESSAGE:",
15161		expectedLocalError: "remote error: unexpected message",
15162	})
15163	testCases = append(testCases, testCase{
15164		testType: clientTest,
15165		name:     "ClientSkipCertificateVerify-TLS13",
15166		config: Config{
15167			MinVersion: VersionTLS13,
15168			MaxVersion: VersionTLS13,
15169			Credential: &rsaChainCertificate,
15170			Bugs: ProtocolBugs{
15171				SkipCertificateVerify: true,
15172			},
15173		},
15174		expectations: connectionExpectations{
15175			peerCertificate: &rsaCertificate,
15176		},
15177		shimCertificate:    &rsaCertificate,
15178		shouldFail:         true,
15179		expectedError:      ":UNEXPECTED_MESSAGE:",
15180		expectedLocalError: "remote error: unexpected message",
15181	})
15182
15183	// If the client or server has 0-RTT enabled but disabled TLS 1.3, it should
15184	// report a reason of protocol_version.
15185	testCases = append(testCases, testCase{
15186		testType: clientTest,
15187		name:     "EarlyDataEnabled-Client-MaxTLS12",
15188		expectations: connectionExpectations{
15189			version: VersionTLS12,
15190		},
15191		flags: []string{
15192			"-enable-early-data",
15193			"-max-version", strconv.Itoa(VersionTLS12),
15194			"-expect-early-data-reason", "protocol_version",
15195		},
15196	})
15197	testCases = append(testCases, testCase{
15198		testType: serverTest,
15199		name:     "EarlyDataEnabled-Server-MaxTLS12",
15200		expectations: connectionExpectations{
15201			version: VersionTLS12,
15202		},
15203		flags: []string{
15204			"-enable-early-data",
15205			"-max-version", strconv.Itoa(VersionTLS12),
15206			"-expect-early-data-reason", "protocol_version",
15207		},
15208	})
15209
15210	// The server additionally reports protocol_version if it enabled TLS 1.3,
15211	// but the peer negotiated TLS 1.2. (The corresponding situation does not
15212	// exist on the client because negotiating TLS 1.2 with a 0-RTT ClientHello
15213	// is a fatal error.)
15214	testCases = append(testCases, testCase{
15215		testType: serverTest,
15216		name:     "EarlyDataEnabled-Server-NegotiateTLS12",
15217		config: Config{
15218			MaxVersion: VersionTLS12,
15219		},
15220		expectations: connectionExpectations{
15221			version: VersionTLS12,
15222		},
15223		flags: []string{
15224			"-enable-early-data",
15225			"-expect-early-data-reason", "protocol_version",
15226		},
15227	})
15228
15229	// On 0-RTT reject, the server may end up negotiating a cipher suite with a
15230	// different PRF hash. Test that the client handles this correctly.
15231	testCases = append(testCases, testCase{
15232		testType: clientTest,
15233		name:     "EarlyData-Reject0RTT-DifferentPRF-Client",
15234		config: Config{
15235			MaxVersion:   VersionTLS13,
15236			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
15237		},
15238		resumeConfig: &Config{
15239			MaxVersion:   VersionTLS13,
15240			CipherSuites: []uint16{TLS_AES_256_GCM_SHA384},
15241		},
15242		resumeSession:           true,
15243		expectResumeRejected:    true,
15244		earlyData:               true,
15245		expectEarlyDataRejected: true,
15246		flags: []string{
15247			"-on-initial-expect-cipher", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
15248			// The client initially reports the old cipher suite while sending
15249			// early data. After processing the 0-RTT reject, it reports the
15250			// true cipher suite.
15251			"-on-resume-expect-cipher", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
15252			"-on-retry-expect-cipher", strconv.Itoa(int(TLS_AES_256_GCM_SHA384)),
15253		},
15254	})
15255	testCases = append(testCases, testCase{
15256		testType: clientTest,
15257		name:     "EarlyData-Reject0RTT-DifferentPRF-HRR-Client",
15258		config: Config{
15259			MaxVersion:   VersionTLS13,
15260			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
15261		},
15262		resumeConfig: &Config{
15263			MaxVersion:   VersionTLS13,
15264			CipherSuites: []uint16{TLS_AES_256_GCM_SHA384},
15265			// P-384 requires a HelloRetryRequest against BoringSSL's default
15266			// configuration. Assert this with ExpectMissingKeyShare.
15267			CurvePreferences: []CurveID{CurveP384},
15268			Bugs: ProtocolBugs{
15269				ExpectMissingKeyShare: true,
15270			},
15271		},
15272		resumeSession:           true,
15273		expectResumeRejected:    true,
15274		earlyData:               true,
15275		expectEarlyDataRejected: true,
15276		flags: []string{
15277			"-on-initial-expect-cipher", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
15278			// The client initially reports the old cipher suite while sending
15279			// early data. After processing the 0-RTT reject, it reports the
15280			// true cipher suite.
15281			"-on-resume-expect-cipher", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
15282			"-on-retry-expect-cipher", strconv.Itoa(int(TLS_AES_256_GCM_SHA384)),
15283		},
15284	})
15285
15286	// Test that the client enforces cipher suite match on 0-RTT accept.
15287	testCases = append(testCases, testCase{
15288		testType: clientTest,
15289		name:     "EarlyData-CipherMismatch-Client-TLS13",
15290		config: Config{
15291			MaxVersion:   VersionTLS13,
15292			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
15293		},
15294		resumeConfig: &Config{
15295			MaxVersion:   VersionTLS13,
15296			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
15297			Bugs: ProtocolBugs{
15298				AlwaysAcceptEarlyData: true,
15299			},
15300		},
15301		resumeSession:      true,
15302		earlyData:          true,
15303		shouldFail:         true,
15304		expectedError:      ":CIPHER_MISMATCH_ON_EARLY_DATA:",
15305		expectedLocalError: "remote error: illegal parameter",
15306	})
15307
15308	// Test that the client can write early data when it has received a partial
15309	// ServerHello..Finished flight. See https://crbug.com/1208784. Note the
15310	// EncryptedExtensions test assumes EncryptedExtensions and Finished are in
15311	// separate records, i.e. that PackHandshakeFlight is disabled.
15312	testCases = append(testCases, testCase{
15313		testType: clientTest,
15314		name:     "EarlyData-WriteAfterServerHello",
15315		config: Config{
15316			MinVersion: VersionTLS13,
15317			MaxVersion: VersionTLS13,
15318			Bugs: ProtocolBugs{
15319				// Write the server response before expecting early data.
15320				ExpectEarlyData:     [][]byte{},
15321				ExpectLateEarlyData: [][]byte{[]byte(shimInitialWrite)},
15322			},
15323		},
15324		resumeSession: true,
15325		earlyData:     true,
15326		flags: []string{
15327			"-async",
15328			"-on-resume-early-write-after-message",
15329			strconv.Itoa(int(typeServerHello)),
15330		},
15331	})
15332	testCases = append(testCases, testCase{
15333		testType: clientTest,
15334		name:     "EarlyData-WriteAfterEncryptedExtensions",
15335		config: Config{
15336			MinVersion: VersionTLS13,
15337			MaxVersion: VersionTLS13,
15338			Bugs: ProtocolBugs{
15339				// Write the server response before expecting early data.
15340				ExpectEarlyData:     [][]byte{},
15341				ExpectLateEarlyData: [][]byte{[]byte(shimInitialWrite)},
15342			},
15343		},
15344		resumeSession: true,
15345		earlyData:     true,
15346		flags: []string{
15347			"-async",
15348			"-on-resume-early-write-after-message",
15349			strconv.Itoa(int(typeEncryptedExtensions)),
15350		},
15351	})
15352}
15353
15354func addTLS13CipherPreferenceTests() {
15355	// Test that client preference is honored if the shim has AES hardware
15356	// and ChaCha20-Poly1305 is preferred otherwise.
15357	testCases = append(testCases, testCase{
15358		testType: serverTest,
15359		name:     "TLS13-CipherPreference-Server-ChaCha20-AES",
15360		config: Config{
15361			MaxVersion: VersionTLS13,
15362			CipherSuites: []uint16{
15363				TLS_CHACHA20_POLY1305_SHA256,
15364				TLS_AES_128_GCM_SHA256,
15365			},
15366			CurvePreferences: []CurveID{CurveX25519},
15367		},
15368		flags: []string{
15369			"-expect-cipher-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
15370			"-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
15371		},
15372	})
15373
15374	testCases = append(testCases, testCase{
15375		testType: serverTest,
15376		name:     "TLS13-CipherPreference-Server-AES-ChaCha20",
15377		config: Config{
15378			MaxVersion: VersionTLS13,
15379			CipherSuites: []uint16{
15380				TLS_AES_128_GCM_SHA256,
15381				TLS_CHACHA20_POLY1305_SHA256,
15382			},
15383			CurvePreferences: []CurveID{CurveX25519},
15384		},
15385		flags: []string{
15386			"-expect-cipher-aes", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
15387			"-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
15388		},
15389	})
15390
15391	// Test that the client orders ChaCha20-Poly1305 and AES-GCM based on
15392	// whether it has AES hardware.
15393	testCases = append(testCases, testCase{
15394		name: "TLS13-CipherPreference-Client",
15395		config: Config{
15396			MaxVersion: VersionTLS13,
15397			// Use the client cipher order. (This is the default but
15398			// is listed to be explicit.)
15399			PreferServerCipherSuites: false,
15400		},
15401		flags: []string{
15402			"-expect-cipher-aes", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
15403			"-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
15404		},
15405	})
15406}
15407
15408func addPeekTests() {
15409	// Test SSL_peek works, including on empty records.
15410	testCases = append(testCases, testCase{
15411		name:             "Peek-Basic",
15412		sendEmptyRecords: 1,
15413		flags:            []string{"-peek-then-read"},
15414	})
15415
15416	// Test SSL_peek can drive the initial handshake.
15417	testCases = append(testCases, testCase{
15418		name: "Peek-ImplicitHandshake",
15419		flags: []string{
15420			"-peek-then-read",
15421			"-implicit-handshake",
15422		},
15423	})
15424
15425	// Test SSL_peek can discover and drive a renegotiation.
15426	testCases = append(testCases, testCase{
15427		name: "Peek-Renegotiate",
15428		config: Config{
15429			MaxVersion: VersionTLS12,
15430		},
15431		renegotiate: 1,
15432		flags: []string{
15433			"-peek-then-read",
15434			"-renegotiate-freely",
15435			"-expect-total-renegotiations", "1",
15436		},
15437	})
15438
15439	// Test SSL_peek can discover a close_notify.
15440	testCases = append(testCases, testCase{
15441		name: "Peek-Shutdown",
15442		config: Config{
15443			Bugs: ProtocolBugs{
15444				ExpectCloseNotify: true,
15445			},
15446		},
15447		flags: []string{
15448			"-peek-then-read",
15449			"-check-close-notify",
15450		},
15451	})
15452
15453	// Test SSL_peek can discover an alert.
15454	testCases = append(testCases, testCase{
15455		name: "Peek-Alert",
15456		config: Config{
15457			Bugs: ProtocolBugs{
15458				SendSpuriousAlert: alertRecordOverflow,
15459			},
15460		},
15461		flags:         []string{"-peek-then-read"},
15462		shouldFail:    true,
15463		expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
15464	})
15465
15466	// Test SSL_peek can handle KeyUpdate.
15467	testCases = append(testCases, testCase{
15468		name: "Peek-KeyUpdate",
15469		config: Config{
15470			MaxVersion: VersionTLS13,
15471		},
15472		sendKeyUpdates:   1,
15473		keyUpdateRequest: keyUpdateNotRequested,
15474		flags:            []string{"-peek-then-read"},
15475	})
15476}
15477
15478func addRecordVersionTests() {
15479	for _, ver := range tlsVersions {
15480		// Test that the record version is enforced.
15481		testCases = append(testCases, testCase{
15482			name: "CheckRecordVersion-" + ver.name,
15483			config: Config{
15484				MinVersion: ver.version,
15485				MaxVersion: ver.version,
15486				Bugs: ProtocolBugs{
15487					SendRecordVersion: 0x03ff,
15488				},
15489			},
15490			shouldFail:    true,
15491			expectedError: ":WRONG_VERSION_NUMBER:",
15492		})
15493
15494		// Test that the ClientHello may use any record version, for
15495		// compatibility reasons.
15496		testCases = append(testCases, testCase{
15497			testType: serverTest,
15498			name:     "LooseInitialRecordVersion-" + ver.name,
15499			config: Config{
15500				MinVersion: ver.version,
15501				MaxVersion: ver.version,
15502				Bugs: ProtocolBugs{
15503					SendInitialRecordVersion: 0x03ff,
15504				},
15505			},
15506		})
15507
15508		// Test that garbage ClientHello record versions are rejected.
15509		testCases = append(testCases, testCase{
15510			testType: serverTest,
15511			name:     "GarbageInitialRecordVersion-" + ver.name,
15512			config: Config{
15513				MinVersion: ver.version,
15514				MaxVersion: ver.version,
15515				Bugs: ProtocolBugs{
15516					SendInitialRecordVersion: 0xffff,
15517				},
15518			},
15519			shouldFail:    true,
15520			expectedError: ":WRONG_VERSION_NUMBER:",
15521		})
15522	}
15523}
15524
15525func addCertificateTests() {
15526	for _, ver := range tlsVersions {
15527		// Test that a certificate chain with intermediate may be sent
15528		// and received as both client and server.
15529		testCases = append(testCases, testCase{
15530			testType: clientTest,
15531			name:     "SendReceiveIntermediate-Client-" + ver.name,
15532			config: Config{
15533				MinVersion: ver.version,
15534				MaxVersion: ver.version,
15535				Credential: &rsaChainCertificate,
15536				ClientAuth: RequireAnyClientCert,
15537			},
15538			expectations: connectionExpectations{
15539				peerCertificate: &rsaChainCertificate,
15540			},
15541			shimCertificate: &rsaChainCertificate,
15542			flags: []string{
15543				"-expect-peer-cert-file", rsaChainCertificate.ChainPath,
15544			},
15545		})
15546
15547		testCases = append(testCases, testCase{
15548			testType: serverTest,
15549			name:     "SendReceiveIntermediate-Server-" + ver.name,
15550			config: Config{
15551				MinVersion: ver.version,
15552				MaxVersion: ver.version,
15553				Credential: &rsaChainCertificate,
15554			},
15555			expectations: connectionExpectations{
15556				peerCertificate: &rsaChainCertificate,
15557			},
15558			shimCertificate: &rsaChainCertificate,
15559			flags: []string{
15560				"-require-any-client-certificate",
15561				"-expect-peer-cert-file", rsaChainCertificate.ChainPath,
15562			},
15563		})
15564
15565		// Test that garbage leaf certificates are properly rejected.
15566		testCases = append(testCases, testCase{
15567			testType: clientTest,
15568			name:     "GarbageCertificate-Client-" + ver.name,
15569			config: Config{
15570				MinVersion: ver.version,
15571				MaxVersion: ver.version,
15572				Credential: &garbageCertificate,
15573			},
15574			shouldFail:         true,
15575			expectedError:      ":CANNOT_PARSE_LEAF_CERT:",
15576			expectedLocalError: "remote error: error decoding message",
15577		})
15578
15579		testCases = append(testCases, testCase{
15580			testType: serverTest,
15581			name:     "GarbageCertificate-Server-" + ver.name,
15582			config: Config{
15583				MinVersion: ver.version,
15584				MaxVersion: ver.version,
15585				Credential: &garbageCertificate,
15586			},
15587			flags:              []string{"-require-any-client-certificate"},
15588			shouldFail:         true,
15589			expectedError:      ":CANNOT_PARSE_LEAF_CERT:",
15590			expectedLocalError: "remote error: error decoding message",
15591		})
15592	}
15593}
15594
15595func addRetainOnlySHA256ClientCertTests() {
15596	for _, ver := range tlsVersions {
15597		// Test that enabling
15598		// SSL_CTX_set_retain_only_sha256_of_client_certs without
15599		// actually requesting a client certificate is a no-op.
15600		testCases = append(testCases, testCase{
15601			testType: serverTest,
15602			name:     "RetainOnlySHA256-NoCert-" + ver.name,
15603			config: Config{
15604				MinVersion: ver.version,
15605				MaxVersion: ver.version,
15606			},
15607			flags: []string{
15608				"-on-initial-retain-only-sha256-client-cert",
15609				"-on-resume-retain-only-sha256-client-cert",
15610			},
15611			resumeSession: true,
15612		})
15613
15614		// Test that when retaining only a SHA-256 certificate is
15615		// enabled, the hash appears as expected.
15616		testCases = append(testCases, testCase{
15617			testType: serverTest,
15618			name:     "RetainOnlySHA256-Cert-" + ver.name,
15619			config: Config{
15620				MinVersion: ver.version,
15621				MaxVersion: ver.version,
15622				Credential: &rsaCertificate,
15623			},
15624			flags: []string{
15625				"-verify-peer",
15626				"-on-initial-retain-only-sha256-client-cert",
15627				"-on-resume-retain-only-sha256-client-cert",
15628				"-on-initial-expect-sha256-client-cert",
15629				"-on-resume-expect-sha256-client-cert",
15630			},
15631			resumeSession: true,
15632		})
15633
15634		// Test that when the config changes from on to off, a
15635		// resumption is rejected because the server now wants the full
15636		// certificate chain.
15637		testCases = append(testCases, testCase{
15638			testType: serverTest,
15639			name:     "RetainOnlySHA256-OnOff-" + ver.name,
15640			config: Config{
15641				MinVersion: ver.version,
15642				MaxVersion: ver.version,
15643				Credential: &rsaCertificate,
15644			},
15645			flags: []string{
15646				"-verify-peer",
15647				"-on-initial-retain-only-sha256-client-cert",
15648				"-on-initial-expect-sha256-client-cert",
15649			},
15650			resumeSession:        true,
15651			expectResumeRejected: true,
15652		})
15653
15654		// Test that when the config changes from off to on, a
15655		// resumption is rejected because the server now wants just the
15656		// hash.
15657		testCases = append(testCases, testCase{
15658			testType: serverTest,
15659			name:     "RetainOnlySHA256-OffOn-" + ver.name,
15660			config: Config{
15661				MinVersion: ver.version,
15662				MaxVersion: ver.version,
15663				Credential: &rsaCertificate,
15664			},
15665			flags: []string{
15666				"-verify-peer",
15667				"-on-resume-retain-only-sha256-client-cert",
15668				"-on-resume-expect-sha256-client-cert",
15669			},
15670			resumeSession:        true,
15671			expectResumeRejected: true,
15672		})
15673	}
15674}
15675
15676func addECDSAKeyUsageTests() {
15677	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
15678	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
15679	if err != nil {
15680		panic(err)
15681	}
15682
15683	template := &x509.Certificate{
15684		SerialNumber: serialNumber,
15685		Subject: pkix.Name{
15686			Organization: []string{"Acme Co"},
15687		},
15688		NotBefore: time.Now(),
15689		NotAfter:  time.Now(),
15690
15691		// An ECC certificate with only the keyAgreement key usgae may
15692		// be used with ECDH, but not ECDSA.
15693		KeyUsage:              x509.KeyUsageKeyAgreement,
15694		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
15695		BasicConstraintsValid: true,
15696	}
15697
15698	cert := generateSingleCertChain(template, &ecdsaP256Key)
15699
15700	for _, ver := range tlsVersions {
15701		if ver.version < VersionTLS12 {
15702			continue
15703		}
15704
15705		testCases = append(testCases, testCase{
15706			testType: clientTest,
15707			name:     "ECDSAKeyUsage-Client-" + ver.name,
15708			config: Config{
15709				MinVersion: ver.version,
15710				MaxVersion: ver.version,
15711				Credential: &cert,
15712			},
15713			shouldFail:    true,
15714			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
15715		})
15716
15717		testCases = append(testCases, testCase{
15718			testType: serverTest,
15719			name:     "ECDSAKeyUsage-Server-" + ver.name,
15720			config: Config{
15721				MinVersion: ver.version,
15722				MaxVersion: ver.version,
15723				Credential: &cert,
15724			},
15725			flags:         []string{"-require-any-client-certificate"},
15726			shouldFail:    true,
15727			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
15728		})
15729	}
15730}
15731
15732func addRSAKeyUsageTests() {
15733	priv := rsaCertificate.PrivateKey.(*rsa.PrivateKey)
15734
15735	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
15736	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
15737	if err != nil {
15738		panic(err)
15739	}
15740
15741	dsTemplate := x509.Certificate{
15742		SerialNumber: serialNumber,
15743		Subject: pkix.Name{
15744			Organization: []string{"Acme Co"},
15745		},
15746		NotBefore: time.Now(),
15747		NotAfter:  time.Now(),
15748
15749		KeyUsage:              x509.KeyUsageDigitalSignature,
15750		BasicConstraintsValid: true,
15751	}
15752
15753	encTemplate := x509.Certificate{
15754		SerialNumber: serialNumber,
15755		Subject: pkix.Name{
15756			Organization: []string{"Acme Co"},
15757		},
15758		NotBefore: time.Now(),
15759		NotAfter:  time.Now(),
15760
15761		KeyUsage:              x509.KeyUsageKeyEncipherment,
15762		BasicConstraintsValid: true,
15763	}
15764
15765	dsCert := generateSingleCertChain(&dsTemplate, priv)
15766
15767	encCert := generateSingleCertChain(&encTemplate, priv)
15768
15769	dsSuites := []uint16{
15770		TLS_AES_128_GCM_SHA256,
15771		TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
15772		TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
15773	}
15774	encSuites := []uint16{
15775		TLS_RSA_WITH_AES_128_GCM_SHA256,
15776		TLS_RSA_WITH_AES_128_CBC_SHA,
15777	}
15778
15779	for _, ver := range tlsVersions {
15780		testCases = append(testCases, testCase{
15781			testType: clientTest,
15782			name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-" + ver.name,
15783			config: Config{
15784				MinVersion:   ver.version,
15785				MaxVersion:   ver.version,
15786				Credential:   &encCert,
15787				CipherSuites: dsSuites,
15788			},
15789			shouldFail:    true,
15790			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
15791		})
15792
15793		testCases = append(testCases, testCase{
15794			testType: clientTest,
15795			name:     "RSAKeyUsage-Client-WantSignature-GotSignature-" + ver.name,
15796			config: Config{
15797				MinVersion:   ver.version,
15798				MaxVersion:   ver.version,
15799				Credential:   &dsCert,
15800				CipherSuites: dsSuites,
15801			},
15802		})
15803
15804		// TLS 1.3 removes the encipherment suites.
15805		if ver.version < VersionTLS13 {
15806			testCases = append(testCases, testCase{
15807				testType: clientTest,
15808				name:     "RSAKeyUsage-Client-WantEncipherment-GotEncipherment" + ver.name,
15809				config: Config{
15810					MinVersion:   ver.version,
15811					MaxVersion:   ver.version,
15812					Credential:   &encCert,
15813					CipherSuites: encSuites,
15814				},
15815			})
15816
15817			testCases = append(testCases, testCase{
15818				testType: clientTest,
15819				name:     "RSAKeyUsage-Client-WantEncipherment-GotSignature-" + ver.name,
15820				config: Config{
15821					MinVersion:   ver.version,
15822					MaxVersion:   ver.version,
15823					Credential:   &dsCert,
15824					CipherSuites: encSuites,
15825				},
15826				shouldFail:    true,
15827				expectedError: ":KEY_USAGE_BIT_INCORRECT:",
15828			})
15829
15830			// In 1.2 and below, we should not enforce without the enforce-rsa-key-usage flag.
15831			testCases = append(testCases, testCase{
15832				testType: clientTest,
15833				name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-Unenforced-" + ver.name,
15834				config: Config{
15835					MinVersion:   ver.version,
15836					MaxVersion:   ver.version,
15837					Credential:   &dsCert,
15838					CipherSuites: encSuites,
15839				},
15840				flags: []string{"-expect-key-usage-invalid", "-ignore-rsa-key-usage"},
15841			})
15842
15843			testCases = append(testCases, testCase{
15844				testType: clientTest,
15845				name:     "RSAKeyUsage-Client-WantEncipherment-GotSignature-Unenforced-" + ver.name,
15846				config: Config{
15847					MinVersion:   ver.version,
15848					MaxVersion:   ver.version,
15849					Credential:   &encCert,
15850					CipherSuites: dsSuites,
15851				},
15852				flags: []string{"-expect-key-usage-invalid", "-ignore-rsa-key-usage"},
15853			})
15854		}
15855
15856		if ver.version >= VersionTLS13 {
15857			// In 1.3 and above, we enforce keyUsage even when disabled.
15858			testCases = append(testCases, testCase{
15859				testType: clientTest,
15860				name:     "RSAKeyUsage-Client-WantSignature-GotEncipherment-AlwaysEnforced-" + ver.name,
15861				config: Config{
15862					MinVersion:   ver.version,
15863					MaxVersion:   ver.version,
15864					Credential:   &encCert,
15865					CipherSuites: dsSuites,
15866				},
15867				flags:         []string{"-ignore-rsa-key-usage"},
15868				shouldFail:    true,
15869				expectedError: ":KEY_USAGE_BIT_INCORRECT:",
15870			})
15871		}
15872
15873		// The server only uses signatures and always enforces it.
15874		testCases = append(testCases, testCase{
15875			testType: serverTest,
15876			name:     "RSAKeyUsage-Server-WantSignature-GotEncipherment-" + ver.name,
15877			config: Config{
15878				MinVersion: ver.version,
15879				MaxVersion: ver.version,
15880				Credential: &encCert,
15881			},
15882			shouldFail:    true,
15883			expectedError: ":KEY_USAGE_BIT_INCORRECT:",
15884			flags:         []string{"-require-any-client-certificate"},
15885		})
15886
15887		testCases = append(testCases, testCase{
15888			testType: serverTest,
15889			name:     "RSAKeyUsage-Server-WantSignature-GotSignature-" + ver.name,
15890			config: Config{
15891				MinVersion: ver.version,
15892				MaxVersion: ver.version,
15893				Credential: &dsCert,
15894			},
15895			flags: []string{"-require-any-client-certificate"},
15896		})
15897
15898	}
15899}
15900
15901func addExtraHandshakeTests() {
15902	// An extra SSL_do_handshake is normally a no-op. These tests use -async
15903	// to ensure there is no transport I/O.
15904	testCases = append(testCases, testCase{
15905		testType: clientTest,
15906		name:     "ExtraHandshake-Client-TLS12",
15907		config: Config{
15908			MinVersion: VersionTLS12,
15909			MaxVersion: VersionTLS12,
15910		},
15911		flags: []string{
15912			"-async",
15913			"-no-op-extra-handshake",
15914		},
15915	})
15916	testCases = append(testCases, testCase{
15917		testType: serverTest,
15918		name:     "ExtraHandshake-Server-TLS12",
15919		config: Config{
15920			MinVersion: VersionTLS12,
15921			MaxVersion: VersionTLS12,
15922		},
15923		flags: []string{
15924			"-async",
15925			"-no-op-extra-handshake",
15926		},
15927	})
15928	testCases = append(testCases, testCase{
15929		testType: clientTest,
15930		name:     "ExtraHandshake-Client-TLS13",
15931		config: Config{
15932			MinVersion: VersionTLS13,
15933			MaxVersion: VersionTLS13,
15934		},
15935		flags: []string{
15936			"-async",
15937			"-no-op-extra-handshake",
15938		},
15939	})
15940	testCases = append(testCases, testCase{
15941		testType: serverTest,
15942		name:     "ExtraHandshake-Server-TLS13",
15943		config: Config{
15944			MinVersion: VersionTLS13,
15945			MaxVersion: VersionTLS13,
15946		},
15947		flags: []string{
15948			"-async",
15949			"-no-op-extra-handshake",
15950		},
15951	})
15952
15953	// An extra SSL_do_handshake is a no-op in server 0-RTT.
15954	testCases = append(testCases, testCase{
15955		testType: serverTest,
15956		name:     "ExtraHandshake-Server-EarlyData-TLS13",
15957		config: Config{
15958			MaxVersion: VersionTLS13,
15959			MinVersion: VersionTLS13,
15960		},
15961		messageCount:  2,
15962		resumeSession: true,
15963		earlyData:     true,
15964		flags: []string{
15965			"-async",
15966			"-no-op-extra-handshake",
15967		},
15968	})
15969
15970	// An extra SSL_do_handshake drives the handshake to completion in False
15971	// Start. We test this by handshaking twice and asserting the False
15972	// Start does not appear to happen. See AlertBeforeFalseStartTest for
15973	// how the test works.
15974	testCases = append(testCases, testCase{
15975		testType: clientTest,
15976		name:     "ExtraHandshake-FalseStart",
15977		config: Config{
15978			MaxVersion:   VersionTLS12,
15979			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
15980			NextProtos:   []string{"foo"},
15981			Bugs: ProtocolBugs{
15982				ExpectFalseStart:          true,
15983				AlertBeforeFalseStartTest: alertAccessDenied,
15984			},
15985		},
15986		flags: []string{
15987			"-handshake-twice",
15988			"-false-start",
15989			"-advertise-alpn", "\x03foo",
15990			"-expect-alpn", "foo",
15991		},
15992		shimWritesFirst:    true,
15993		shouldFail:         true,
15994		expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
15995		expectedLocalError: "tls: peer did not false start: EOF",
15996	})
15997}
15998
15999// Test that omitted and empty extensions blocks are tolerated.
16000func addOmitExtensionsTests() {
16001	// Check the ExpectOmitExtensions setting works.
16002	testCases = append(testCases, testCase{
16003		testType: serverTest,
16004		name:     "ExpectOmitExtensions",
16005		config: Config{
16006			MinVersion: VersionTLS12,
16007			MaxVersion: VersionTLS12,
16008			Bugs: ProtocolBugs{
16009				ExpectOmitExtensions: true,
16010			},
16011		},
16012		shouldFail:         true,
16013		expectedLocalError: "tls: ServerHello did not omit extensions",
16014	})
16015
16016	for _, ver := range tlsVersions {
16017		if ver.version > VersionTLS12 {
16018			continue
16019		}
16020
16021		testCases = append(testCases, testCase{
16022			testType: serverTest,
16023			name:     "OmitExtensions-ClientHello-" + ver.name,
16024			config: Config{
16025				MinVersion:             ver.version,
16026				MaxVersion:             ver.version,
16027				SessionTicketsDisabled: true,
16028				Bugs: ProtocolBugs{
16029					OmitExtensions: true,
16030					// With no client extensions, the ServerHello must not have
16031					// extensions. It should then omit the extensions field.
16032					ExpectOmitExtensions: true,
16033				},
16034			},
16035		})
16036
16037		testCases = append(testCases, testCase{
16038			testType: serverTest,
16039			name:     "EmptyExtensions-ClientHello-" + ver.name,
16040			config: Config{
16041				MinVersion:             ver.version,
16042				MaxVersion:             ver.version,
16043				SessionTicketsDisabled: true,
16044				Bugs: ProtocolBugs{
16045					EmptyExtensions: true,
16046					// With no client extensions, the ServerHello must not have
16047					// extensions. It should then omit the extensions field.
16048					ExpectOmitExtensions: true,
16049				},
16050			},
16051		})
16052
16053		testCases = append(testCases, testCase{
16054			testType: clientTest,
16055			name:     "OmitExtensions-ServerHello-" + ver.name,
16056			config: Config{
16057				MinVersion:             ver.version,
16058				MaxVersion:             ver.version,
16059				SessionTicketsDisabled: true,
16060				Bugs: ProtocolBugs{
16061					OmitExtensions: true,
16062					// Disable all ServerHello extensions so
16063					// OmitExtensions works.
16064					NoExtendedMasterSecret:        true,
16065					NoRenegotiationInfo:           true,
16066					NoOCSPStapling:                true,
16067					NoSignedCertificateTimestamps: true,
16068				},
16069			},
16070		})
16071
16072		testCases = append(testCases, testCase{
16073			testType: clientTest,
16074			name:     "EmptyExtensions-ServerHello-" + ver.name,
16075			config: Config{
16076				MinVersion:             ver.version,
16077				MaxVersion:             ver.version,
16078				SessionTicketsDisabled: true,
16079				Bugs: ProtocolBugs{
16080					EmptyExtensions: true,
16081					// Disable all ServerHello extensions so
16082					// EmptyExtensions works.
16083					NoExtendedMasterSecret:        true,
16084					NoRenegotiationInfo:           true,
16085					NoOCSPStapling:                true,
16086					NoSignedCertificateTimestamps: true,
16087				},
16088			},
16089		})
16090	}
16091}
16092
16093const (
16094	shrinkingCompressionAlgID = 0xff01
16095	expandingCompressionAlgID = 0xff02
16096	randomCompressionAlgID    = 0xff03
16097)
16098
16099var (
16100	// shrinkingPrefix is the first two bytes of a Certificate message.
16101	shrinkingPrefix = []byte{0, 0}
16102	// expandingPrefix is just some arbitrary byte string. This has to match the
16103	// value in the shim.
16104	expandingPrefix = []byte{1, 2, 3, 4}
16105)
16106
16107var shrinkingCompression = CertCompressionAlg{
16108	Compress: func(uncompressed []byte) []byte {
16109		if !bytes.HasPrefix(uncompressed, shrinkingPrefix) {
16110			panic(fmt.Sprintf("cannot compress certificate message %x", uncompressed))
16111		}
16112		return uncompressed[len(shrinkingPrefix):]
16113	},
16114	Decompress: func(out []byte, compressed []byte) bool {
16115		if len(out) != len(shrinkingPrefix)+len(compressed) {
16116			return false
16117		}
16118
16119		copy(out, shrinkingPrefix)
16120		copy(out[len(shrinkingPrefix):], compressed)
16121		return true
16122	},
16123}
16124
16125var expandingCompression = CertCompressionAlg{
16126	Compress: func(uncompressed []byte) []byte {
16127		ret := make([]byte, 0, len(expandingPrefix)+len(uncompressed))
16128		ret = append(ret, expandingPrefix...)
16129		return append(ret, uncompressed...)
16130	},
16131	Decompress: func(out []byte, compressed []byte) bool {
16132		if !bytes.HasPrefix(compressed, expandingPrefix) {
16133			return false
16134		}
16135		copy(out, compressed[len(expandingPrefix):])
16136		return true
16137	},
16138}
16139
16140var randomCompression = CertCompressionAlg{
16141	Compress: func(uncompressed []byte) []byte {
16142		ret := make([]byte, 1+len(uncompressed))
16143		if _, err := rand.Read(ret[:1]); err != nil {
16144			panic(err)
16145		}
16146		copy(ret[1:], uncompressed)
16147		return ret
16148	},
16149	Decompress: func(out []byte, compressed []byte) bool {
16150		if len(compressed) != 1+len(out) {
16151			return false
16152		}
16153		copy(out, compressed[1:])
16154		return true
16155	},
16156}
16157
16158func addCertCompressionTests() {
16159	for _, ver := range tlsVersions {
16160		if ver.version < VersionTLS12 {
16161			continue
16162		}
16163
16164		// Duplicate compression algorithms is an error, even if nothing is
16165		// configured.
16166		testCases = append(testCases, testCase{
16167			testType: serverTest,
16168			name:     "DuplicateCertCompressionExt-" + ver.name,
16169			config: Config{
16170				MinVersion: ver.version,
16171				MaxVersion: ver.version,
16172				Bugs: ProtocolBugs{
16173					DuplicateCompressedCertAlgs: true,
16174				},
16175			},
16176			shouldFail:    true,
16177			expectedError: ":ERROR_PARSING_EXTENSION:",
16178		})
16179
16180		// With compression algorithms configured, an duplicate values should still
16181		// be an error.
16182		testCases = append(testCases, testCase{
16183			testType: serverTest,
16184			name:     "DuplicateCertCompressionExt2-" + ver.name,
16185			flags:    []string{"-install-cert-compression-algs"},
16186			config: Config{
16187				MinVersion: ver.version,
16188				MaxVersion: ver.version,
16189				Bugs: ProtocolBugs{
16190					DuplicateCompressedCertAlgs: true,
16191				},
16192			},
16193			shouldFail:    true,
16194			expectedError: ":ERROR_PARSING_EXTENSION:",
16195		})
16196
16197		if ver.version < VersionTLS13 {
16198			testCases = append(testCases, testCase{
16199				testType: serverTest,
16200				name:     "CertCompressionIgnoredBefore13-" + ver.name,
16201				flags:    []string{"-install-cert-compression-algs"},
16202				config: Config{
16203					MinVersion: ver.version,
16204					MaxVersion: ver.version,
16205					CertCompressionAlgs: map[uint16]CertCompressionAlg{
16206						expandingCompressionAlgID: expandingCompression,
16207					},
16208				},
16209			})
16210
16211			continue
16212		}
16213
16214		testCases = append(testCases, testCase{
16215			testType: serverTest,
16216			name:     "CertCompressionExpands-" + ver.name,
16217			flags:    []string{"-install-cert-compression-algs"},
16218			config: Config{
16219				MinVersion: ver.version,
16220				MaxVersion: ver.version,
16221				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16222					expandingCompressionAlgID: expandingCompression,
16223				},
16224				Bugs: ProtocolBugs{
16225					ExpectedCompressedCert: expandingCompressionAlgID,
16226				},
16227			},
16228		})
16229
16230		testCases = append(testCases, testCase{
16231			testType: serverTest,
16232			name:     "CertCompressionShrinks-" + ver.name,
16233			flags:    []string{"-install-cert-compression-algs"},
16234			config: Config{
16235				MinVersion: ver.version,
16236				MaxVersion: ver.version,
16237				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16238					shrinkingCompressionAlgID: shrinkingCompression,
16239				},
16240				Bugs: ProtocolBugs{
16241					ExpectedCompressedCert: shrinkingCompressionAlgID,
16242				},
16243			},
16244		})
16245
16246		// Test that the shim behaves consistently if the compression function
16247		// is non-deterministic. This is intended to model version differences
16248		// between the shim and handshaker with handshake hints, but it is also
16249		// useful in confirming we only call the callbacks once.
16250		testCases = append(testCases, testCase{
16251			testType: serverTest,
16252			name:     "CertCompressionRandom-" + ver.name,
16253			flags:    []string{"-install-cert-compression-algs"},
16254			config: Config{
16255				MinVersion: ver.version,
16256				MaxVersion: ver.version,
16257				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16258					randomCompressionAlgID: randomCompression,
16259				},
16260				Bugs: ProtocolBugs{
16261					ExpectedCompressedCert: randomCompressionAlgID,
16262				},
16263			},
16264		})
16265
16266		// With both algorithms configured, the server should pick its most
16267		// preferable. (Which is expandingCompressionAlgID.)
16268		testCases = append(testCases, testCase{
16269			testType: serverTest,
16270			name:     "CertCompressionPriority-" + ver.name,
16271			flags:    []string{"-install-cert-compression-algs"},
16272			config: Config{
16273				MinVersion: ver.version,
16274				MaxVersion: ver.version,
16275				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16276					shrinkingCompressionAlgID: shrinkingCompression,
16277					expandingCompressionAlgID: expandingCompression,
16278				},
16279				Bugs: ProtocolBugs{
16280					ExpectedCompressedCert: expandingCompressionAlgID,
16281				},
16282			},
16283		})
16284
16285		// With no common algorithms configured, the server should decline
16286		// compression.
16287		testCases = append(testCases, testCase{
16288			testType: serverTest,
16289			name:     "CertCompressionNoCommonAlgs-" + ver.name,
16290			flags:    []string{"-install-one-cert-compression-alg", strconv.Itoa(shrinkingCompressionAlgID)},
16291			config: Config{
16292				MinVersion: ver.version,
16293				MaxVersion: ver.version,
16294				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16295					expandingCompressionAlgID: expandingCompression,
16296				},
16297				Bugs: ProtocolBugs{
16298					ExpectUncompressedCert: true,
16299				},
16300			},
16301		})
16302
16303		testCases = append(testCases, testCase{
16304			testType: clientTest,
16305			name:     "CertCompressionExpandsClient-" + ver.name,
16306			flags:    []string{"-install-cert-compression-algs"},
16307			config: Config{
16308				MinVersion: ver.version,
16309				MaxVersion: ver.version,
16310				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16311					expandingCompressionAlgID: expandingCompression,
16312				},
16313				Bugs: ProtocolBugs{
16314					ExpectedCompressedCert: expandingCompressionAlgID,
16315				},
16316			},
16317		})
16318
16319		testCases = append(testCases, testCase{
16320			testType: clientTest,
16321			name:     "CertCompressionShrinksClient-" + ver.name,
16322			flags:    []string{"-install-cert-compression-algs"},
16323			config: Config{
16324				MinVersion: ver.version,
16325				MaxVersion: ver.version,
16326				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16327					shrinkingCompressionAlgID: shrinkingCompression,
16328				},
16329				Bugs: ProtocolBugs{
16330					ExpectedCompressedCert: shrinkingCompressionAlgID,
16331				},
16332			},
16333		})
16334
16335		testCases = append(testCases, testCase{
16336			testType: clientTest,
16337			name:     "CertCompressionBadAlgIDClient-" + ver.name,
16338			flags:    []string{"-install-cert-compression-algs"},
16339			config: Config{
16340				MinVersion: ver.version,
16341				MaxVersion: ver.version,
16342				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16343					shrinkingCompressionAlgID: shrinkingCompression,
16344				},
16345				Bugs: ProtocolBugs{
16346					ExpectedCompressedCert:   shrinkingCompressionAlgID,
16347					SendCertCompressionAlgID: 1234,
16348				},
16349			},
16350			shouldFail:    true,
16351			expectedError: ":UNKNOWN_CERT_COMPRESSION_ALG:",
16352		})
16353
16354		testCases = append(testCases, testCase{
16355			testType: clientTest,
16356			name:     "CertCompressionTooSmallClient-" + ver.name,
16357			flags:    []string{"-install-cert-compression-algs"},
16358			config: Config{
16359				MinVersion: ver.version,
16360				MaxVersion: ver.version,
16361				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16362					shrinkingCompressionAlgID: shrinkingCompression,
16363				},
16364				Bugs: ProtocolBugs{
16365					ExpectedCompressedCert:     shrinkingCompressionAlgID,
16366					SendCertUncompressedLength: 12,
16367				},
16368			},
16369			shouldFail:    true,
16370			expectedError: ":CERT_DECOMPRESSION_FAILED:",
16371		})
16372
16373		testCases = append(testCases, testCase{
16374			testType: clientTest,
16375			name:     "CertCompressionTooLargeClient-" + ver.name,
16376			flags:    []string{"-install-cert-compression-algs"},
16377			config: Config{
16378				MinVersion: ver.version,
16379				MaxVersion: ver.version,
16380				CertCompressionAlgs: map[uint16]CertCompressionAlg{
16381					shrinkingCompressionAlgID: shrinkingCompression,
16382				},
16383				Bugs: ProtocolBugs{
16384					ExpectedCompressedCert:     shrinkingCompressionAlgID,
16385					SendCertUncompressedLength: 1 << 20,
16386				},
16387			},
16388			shouldFail:    true,
16389			expectedError: ":UNCOMPRESSED_CERT_TOO_LARGE:",
16390		})
16391	}
16392}
16393
16394func addJDK11WorkaroundTests() {
16395	// Test the client treats the JDK 11 downgrade random like the usual one.
16396	testCases = append(testCases, testCase{
16397		testType: clientTest,
16398		name:     "Client-RejectJDK11DowngradeRandom",
16399		config: Config{
16400			MaxVersion: VersionTLS12,
16401			Bugs: ProtocolBugs{
16402				SendJDK11DowngradeRandom: true,
16403			},
16404		},
16405		shouldFail:         true,
16406		expectedError:      ":TLS13_DOWNGRADE:",
16407		expectedLocalError: "remote error: illegal parameter",
16408	})
16409	testCases = append(testCases, testCase{
16410		testType: clientTest,
16411		name:     "Client-AcceptJDK11DowngradeRandom",
16412		config: Config{
16413			MaxVersion: VersionTLS12,
16414			Bugs: ProtocolBugs{
16415				SendJDK11DowngradeRandom: true,
16416			},
16417		},
16418		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
16419	})
16420
16421	var clientHelloTests = []struct {
16422		clientHello []byte
16423		isJDK11     bool
16424	}{
16425		{
16426			// A default JDK 11 ClientHello.
16427			decodeHexOrPanic("010001a9030336a379aa355a22a064b4402760efae1c73977b0b4c975efc7654c35677723dde201fe3f8a2bca60418a68f72463ea19f3c241e7cbfceb347e451a62bd2417d8981005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000106000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b0009080304030303020301002d000201010033004700450017004104721f007464cb08a0f36e093ad178eb78d6968df20077b2dd882694a85dc4c9884caf5092db41f16cc3f8d41f59426992fa5e32cfb9ad08deee752cdd95b1a6b5"),
16428			true,
16429		},
16430		{
16431			// The above with supported_versions and
16432			// psk_key_exchange_modes in the wrong order.
16433			decodeHexOrPanic("010001a9030336a379aa355a22a064b4402760efae1c73977b0b4c975efc7654c35677723dde201fe3f8a2bca60418a68f72463ea19f3c241e7cbfceb347e451a62bd2417d8981005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000106000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002d00020101002b00090803040303030203010033004700450017004104721f007464cb08a0f36e093ad178eb78d6968df20077b2dd882694a85dc4c9884caf5092db41f16cc3f8d41f59426992fa5e32cfb9ad08deee752cdd95b1a6b5"),
16434			false,
16435		},
16436		{
16437			// The above with a padding extension added at the end.
16438			decodeHexOrPanic("010001b4030336a379aa355a22a064b4402760efae1c73977b0b4c975efc7654c35677723dde201fe3f8a2bca60418a68f72463ea19f3c241e7cbfceb347e451a62bd2417d8981005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000111000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b0009080304030303020301002d000201010033004700450017004104721f007464cb08a0f36e093ad178eb78d6968df20077b2dd882694a85dc4c9884caf5092db41f16cc3f8d41f59426992fa5e32cfb9ad08deee752cdd95b1a6b50015000700000000000000"),
16439			false,
16440		},
16441		{
16442			// A JDK 11 ClientHello offering a TLS 1.3 PSK.
16443			decodeHexOrPanic("0100024c0303a8d71b20f060545a398226e807d21371a7a02b7ca2f96f476c2dea7e5860c5a400005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff010001c9000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b0009080304030303020301002d000201010033004700450017004104aaec585ea9e121b24710a23560571322b2cf8ab8cd14e5762ef0486d8a6d0ecd721d8f2abda2eb8ed5ab7195505660450f49bba94bbf0c3f0070a531d9a1be4f002900cb00a600a0e6f7586d9a2bf64a54c1adf55a2f76657047e8e88e26629e2e7b9d630941e06fd87792770f6834e159a70b252157a9b4b082183f24629c8ff5049088b07ce37c49de8cf752a2ed7a545aff63bdc7a1b18e1bc201f23f159ee75d4987a04e00f840824f764691ab83a20e3032646e793065874cdb46138a52f50ed71406f399f96f9309eba4e5b1966148c22a63dc4aa1364269dd41dd5cc0e848d07af0095622c52cfcfc00212009cc315259e2328d65ad17a3de7c182c7874140a9356fecdd4614657806cd659"),
16444			true,
16445		},
16446		{
16447			// A JDK 11 ClientHello offering a TLS 1.2 session.
16448			decodeHexOrPanic("010001a903038cdec49f4836d064a75046c93f22d0b9c2cf4900917332e6f0e1f41d692d3146201a3e99047492285ec65ab4e0eeee59f8f9d1eb7687398887bcd7b81353e93923005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000106000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b0009080304030303020301002d0002010100330047004500170041041c83c42fcd8fc06265b9f6e4f076f7e7ee17ace915c587845c0e1bc8cd177f904befeb611b682cae4702509a5f5d0c7162a282b8152d843169b91136e7c6f3e7"),
16449			true,
16450		},
16451		{
16452			// A JDK 11 ClientHello with EMS disabled.
16453			decodeHexOrPanic("010001a50303323a857c324a9ef57d6e2544d129073830385cb1dc75ea79f6a2ec8ae09d2e7320f85fdd081678874c67ebab235e6d6a81d947f690bc0af9be4d39854ed67d9ef9005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000102000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b040105010601040203030301030202030201020200110009000702000400000000002b0009080304030303020301002d0002010100330047004500170041049c904c4850b495d75522f955d79e9cabea065c90279d6037a101a4c4ee712afc93ad0df5d12d287d53e458c7075d9a3ce3969c939bb62222bda779cecf54a603"),
16454			true,
16455		},
16456		{
16457			// A JDK 11 ClientHello with OCSP stapling disabled.
16458			decodeHexOrPanic("0100019303038a50481dc85ee4f6581670821c50f2b3d34ac3251dc6e9b751bfd2521ab47ab02069a963c5486034c37ae0577ddb4c2db28cab592380ef8e4599d1305148712112005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff010000f0000000080006000003736e69000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b040105010601040203030301030202030201020200170000002b0009080304030303020301002d00020101003300470045001700410438a97824f842c549e3c339322d8b2dbaa85d10bd7bca9c969376cb0c60b1e929eb4d13db38dcb0082ad8c637b24f55466a9acbb0b63634c1f431ec8342cf720d"),
16459			true,
16460		},
16461		{
16462			// A JDK 11 ClientHello configured with a smaller set of
16463			// ciphers.
16464			decodeHexOrPanic("0100015603036f5706bbdf1dcae671cd9be043603f5ed20f8fc195b426504cafb4f353edb0012007aabd35e588bc2504a72eda42cbbf89d69cfc0a6a1d77db0d757606f1f4811800061301c02bc02f01000107000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b00050403040303002d000201010033004700450017004104d283f3d5a90259b61d43ea1511211f568ce5d18457326b717e1f9d6b7d1476f2b51cdc3c798d3bdfba5095edff0ffd0540f6bc0c324bd9744f3b3f24317496e3ff01000100"),
16465			true,
16466		},
16467		{
16468			// The above with TLS_CHACHA20_POLY1305_SHA256 added,
16469			// which JDK 11 does not support.
16470			decodeHexOrPanic("0100015803036f5706bbdf1dcae671cd9be043603f5ed20f8fc195b426504cafb4f353edb0012007aabd35e588bc2504a72eda42cbbf89d69cfc0a6a1d77db0d757606f1f48118000813011303c02bc02f01000107000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b00050403040303002d000201010033004700450017004104d283f3d5a90259b61d43ea1511211f568ce5d18457326b717e1f9d6b7d1476f2b51cdc3c798d3bdfba5095edff0ffd0540f6bc0c324bd9744f3b3f24317496e3ff01000100"),
16471			false,
16472		},
16473		{
16474			// The above with X25519 added, which JDK 11 does not
16475			// support.
16476			decodeHexOrPanic("0100015803036f5706bbdf1dcae671cd9be043603f5ed20f8fc195b426504cafb4f353edb0012007aabd35e588bc2504a72eda42cbbf89d69cfc0a6a1d77db0d757606f1f4811800061301c02bc02f01000109000000080006000003736e69000500050100000000000a00220020001d0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020011000900070200040000000000170000002b00050403040303002d000201010033004700450017004104d283f3d5a90259b61d43ea1511211f568ce5d18457326b717e1f9d6b7d1476f2b51cdc3c798d3bdfba5095edff0ffd0540f6bc0c324bd9744f3b3f24317496e3ff01000100"),
16477			false,
16478		},
16479		{
16480			// A JDK 11 ClientHello with ALPN protocols configured.
16481			decodeHexOrPanic("010001bb0303c0e0ea707b00c5311eb09cabd58626692cebfaefaef7265637e4550811dae16220da86d6eea04e214e873675223f08a6926bcf79f16d866280bdbab85e9e09c3ff005a13011302c02cc02bc030009dc02ec032009f00a3c02f009cc02dc031009e00a2c024c028003dc026c02a006b006ac00ac0140035c005c00f00390038c023c027003cc025c02900670040c009c013002fc004c00e0033003200ff01000118000000080006000003736e69000500050100000000000a0020001e0017001800190009000a000b000c000d000e001601000101010201030104000b00020100000d002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020032002800260403050306030804080508060809080a080b04010501060104020303030103020203020102020010000e000c02683208687474702f312e310011000900070200040000000000170000002b0009080304030303020301002d00020101003300470045001700410416def07c1d66ddde5fc9dcc328c8e77022d321c590c0d30cb41d515b38dca34540819a216c6c053bd47b9068f4f6b960f03647de4e36e8b7ffeea78f7252e3d9"),
16482			true,
16483		},
16484	}
16485	for i, t := range clientHelloTests {
16486		expectedVersion := uint16(VersionTLS13)
16487		if t.isJDK11 {
16488			expectedVersion = VersionTLS12
16489		}
16490
16491		// In each of these tests, we set DefaultCurves to P-256 to
16492		// match the test inputs. SendClientHelloWithFixes requires the
16493		// key_shares extension to match in type.
16494
16495		// With the workaround enabled, we should negotiate TLS 1.2 on
16496		// JDK 11 ClientHellos.
16497		testCases = append(testCases, testCase{
16498			testType: serverTest,
16499			name:     fmt.Sprintf("Server-JDK11-%d", i),
16500			config: Config{
16501				MaxVersion:    VersionTLS13,
16502				DefaultCurves: []CurveID{CurveP256},
16503				Bugs: ProtocolBugs{
16504					SendClientHelloWithFixes:   t.clientHello,
16505					ExpectJDK11DowngradeRandom: t.isJDK11,
16506				},
16507			},
16508			expectations: connectionExpectations{
16509				version: expectedVersion,
16510			},
16511			flags: []string{"-jdk11-workaround"},
16512		})
16513
16514		// With the workaround disabled, we always negotiate TLS 1.3.
16515		testCases = append(testCases, testCase{
16516			testType: serverTest,
16517			name:     fmt.Sprintf("Server-JDK11-NoWorkaround-%d", i),
16518			config: Config{
16519				MaxVersion:    VersionTLS13,
16520				DefaultCurves: []CurveID{CurveP256},
16521				Bugs: ProtocolBugs{
16522					SendClientHelloWithFixes:   t.clientHello,
16523					ExpectJDK11DowngradeRandom: false,
16524				},
16525			},
16526			expectations: connectionExpectations{
16527				version: VersionTLS13,
16528			},
16529		})
16530
16531		// If the server does not support TLS 1.3, the workaround should
16532		// be a no-op. In particular, it should not send the downgrade
16533		// signal.
16534		testCases = append(testCases, testCase{
16535			testType: serverTest,
16536			name:     fmt.Sprintf("Server-JDK11-TLS12-%d", i),
16537			config: Config{
16538				MaxVersion:    VersionTLS13,
16539				DefaultCurves: []CurveID{CurveP256},
16540				Bugs: ProtocolBugs{
16541					SendClientHelloWithFixes:   t.clientHello,
16542					ExpectJDK11DowngradeRandom: false,
16543				},
16544			},
16545			expectations: connectionExpectations{
16546				version: VersionTLS12,
16547			},
16548			flags: []string{
16549				"-jdk11-workaround",
16550				"-max-version", strconv.Itoa(VersionTLS12),
16551			},
16552		})
16553	}
16554}
16555
16556func addDelegatedCredentialTests() {
16557	p256DC := createDelegatedCredential(&rsaCertificate, delegatedCredentialConfig{
16558		dcAlgo: signatureECDSAWithP256AndSHA256,
16559		algo:   signatureRSAPSSWithSHA256,
16560	})
16561
16562	testCases = append(testCases, testCase{
16563		testType: serverTest,
16564		name:     "DelegatedCredentials-NoClientSupport",
16565		config: Config{
16566			MinVersion: VersionTLS13,
16567			MaxVersion: VersionTLS13,
16568		},
16569		shimCredentials: []*Credential{p256DC, &rsaCertificate},
16570		flags:           []string{"-expect-selected-credential", "1"},
16571		expectations: connectionExpectations{
16572			peerCertificate: &rsaCertificate,
16573		},
16574	})
16575
16576	testCases = append(testCases, testCase{
16577		testType: serverTest,
16578		name:     "DelegatedCredentials-Basic",
16579		config: Config{
16580			MinVersion:                    VersionTLS13,
16581			MaxVersion:                    VersionTLS13,
16582			DelegatedCredentialAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
16583		},
16584		shimCredentials: []*Credential{p256DC, &rsaCertificate},
16585		flags:           []string{"-expect-selected-credential", "0"},
16586		expectations: connectionExpectations{
16587			peerCertificate: p256DC,
16588		},
16589	})
16590
16591	testCases = append(testCases, testCase{
16592		testType: serverTest,
16593		name:     "DelegatedCredentials-ExactAlgorithmMatch",
16594		config: Config{
16595			MinVersion: VersionTLS13,
16596			MaxVersion: VersionTLS13,
16597			// Test that the server doesn't mix up the two signature algorithm
16598			// fields. These options are a match because the signature_algorithms
16599			// extension matches against the signature on the delegated
16600			// credential, while the delegated_credential extension matches
16601			// against the signature made by the delegated credential.
16602			VerifySignatureAlgorithms:     []signatureAlgorithm{signatureRSAPSSWithSHA256},
16603			DelegatedCredentialAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
16604		},
16605		shimCredentials: []*Credential{p256DC, &rsaCertificate},
16606		flags:           []string{"-expect-selected-credential", "0"},
16607		expectations: connectionExpectations{
16608			peerCertificate: p256DC,
16609		},
16610	})
16611
16612	testCases = append(testCases, testCase{
16613		testType: serverTest,
16614		name:     "DelegatedCredentials-SigAlgoMissing",
16615		config: Config{
16616			MinVersion: VersionTLS13,
16617			MaxVersion: VersionTLS13,
16618			// If the client doesn't support the signature in the delegated credential,
16619			// the server should not use delegated credentials.
16620			VerifySignatureAlgorithms:     []signatureAlgorithm{signatureRSAPSSWithSHA384},
16621			DelegatedCredentialAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
16622		},
16623		shimCredentials: []*Credential{p256DC, &rsaCertificate},
16624		flags:           []string{"-expect-selected-credential", "1"},
16625		expectations: connectionExpectations{
16626			peerCertificate: &rsaCertificate,
16627		},
16628	})
16629
16630	testCases = append(testCases, testCase{
16631		testType: serverTest,
16632		name:     "DelegatedCredentials-CertVerifySigAlgoMissing",
16633		config: Config{
16634			MinVersion: VersionTLS13,
16635			MaxVersion: VersionTLS13,
16636			// If the client doesn't support the delegated credential's
16637			// CertificateVerify algorithm, the server should not use delegated
16638			// credentials.
16639			VerifySignatureAlgorithms:     []signatureAlgorithm{signatureRSAPSSWithSHA256},
16640			DelegatedCredentialAlgorithms: []signatureAlgorithm{signatureECDSAWithP384AndSHA384},
16641		},
16642		shimCredentials: []*Credential{p256DC, &rsaCertificate},
16643		flags:           []string{"-expect-selected-credential", "1"},
16644		expectations: connectionExpectations{
16645			peerCertificate: &rsaCertificate,
16646		},
16647	})
16648
16649	// Delegated credentials are not supported at TLS 1.2, even if the client
16650	// sends the extension.
16651	testCases = append(testCases, testCase{
16652		testType: serverTest,
16653		name:     "DelegatedCredentials-TLS12-Forbidden",
16654		config: Config{
16655			MinVersion:                    VersionTLS12,
16656			MaxVersion:                    VersionTLS12,
16657			DelegatedCredentialAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
16658		},
16659		shimCredentials: []*Credential{p256DC, &rsaCertificate},
16660		flags:           []string{"-expect-selected-credential", "1"},
16661		expectations: connectionExpectations{
16662			peerCertificate: &rsaCertificate,
16663		},
16664	})
16665
16666	// Generate another delegated credential, so we can get the keys out of sync.
16667	dcWrongKey := createDelegatedCredential(&rsaCertificate, delegatedCredentialConfig{
16668		algo: signatureRSAPSSWithSHA256,
16669	})
16670	dcWrongKey.DelegatedCredential = p256DC.DelegatedCredential
16671	testCases = append(testCases, testCase{
16672		testType: serverTest,
16673		name:     "DelegatedCredentials-KeyMismatch",
16674		// The handshake hints version of the test will, as a side effect, use a
16675		// custom private key. Custom private keys can't be checked for key
16676		// mismatches.
16677		skipHints:       true,
16678		shimCredentials: []*Credential{dcWrongKey},
16679		shouldFail:      true,
16680		expectedError:   ":KEY_VALUES_MISMATCH:",
16681	})
16682
16683	// RSA delegated credentials should be rejected at configuration time.
16684	rsaDC := createDelegatedCredential(&rsaCertificate, delegatedCredentialConfig{
16685		algo:   signatureRSAPSSWithSHA256,
16686		dcAlgo: signatureRSAPSSWithSHA256,
16687	})
16688	testCases = append(testCases, testCase{
16689		testType:        serverTest,
16690		name:            "DelegatedCredentials-NoRSA",
16691		shimCredentials: []*Credential{rsaDC},
16692		shouldFail:      true,
16693		expectedError:   ":INVALID_SIGNATURE_ALGORITHM:",
16694	})
16695
16696	// If configured with multiple delegated credentials, the server can cleanly
16697	// select the first one that works.
16698	p384DC := createDelegatedCredential(&rsaCertificate, delegatedCredentialConfig{
16699		dcAlgo: signatureECDSAWithP384AndSHA384,
16700		algo:   signatureRSAPSSWithSHA256,
16701	})
16702	testCases = append(testCases, testCase{
16703		testType: serverTest,
16704		name:     "DelegatedCredentials-Multiple",
16705		config: Config{
16706			DelegatedCredentialAlgorithms: []signatureAlgorithm{signatureECDSAWithP384AndSHA384},
16707		},
16708		shimCredentials: []*Credential{p256DC, p384DC},
16709		flags:           []string{"-expect-selected-credential", "1"},
16710		expectations: connectionExpectations{
16711			peerCertificate: p384DC,
16712		},
16713	})
16714}
16715
16716type echCipher struct {
16717	name   string
16718	cipher HPKECipherSuite
16719}
16720
16721var echCiphers = []echCipher{
16722	{
16723		name:   "HKDF-SHA256-AES-128-GCM",
16724		cipher: HPKECipherSuite{KDF: hpke.HKDFSHA256, AEAD: hpke.AES128GCM},
16725	},
16726	{
16727		name:   "HKDF-SHA256-AES-256-GCM",
16728		cipher: HPKECipherSuite{KDF: hpke.HKDFSHA256, AEAD: hpke.AES256GCM},
16729	}, {
16730		name:   "HKDF-SHA256-ChaCha20-Poly1305",
16731		cipher: HPKECipherSuite{KDF: hpke.HKDFSHA256, AEAD: hpke.ChaCha20Poly1305},
16732	},
16733}
16734
16735// generateServerECHConfig constructs a ServerECHConfig with a fresh X25519
16736// keypair and using |template| as a template for the ECHConfig. If fields are
16737// omitted, defaults are used.
16738func generateServerECHConfig(template *ECHConfig) ServerECHConfig {
16739	publicKey, secretKey, err := hpke.GenerateKeyPairX25519()
16740	if err != nil {
16741		panic(err)
16742	}
16743	templateCopy := *template
16744	if templateCopy.KEM == 0 {
16745		templateCopy.KEM = hpke.X25519WithHKDFSHA256
16746	}
16747	if len(templateCopy.PublicKey) == 0 {
16748		templateCopy.PublicKey = publicKey
16749	}
16750	if len(templateCopy.CipherSuites) == 0 {
16751		templateCopy.CipherSuites = make([]HPKECipherSuite, len(echCiphers))
16752		for i, cipher := range echCiphers {
16753			templateCopy.CipherSuites[i] = cipher.cipher
16754		}
16755	}
16756	if len(templateCopy.PublicName) == 0 {
16757		templateCopy.PublicName = "public.example"
16758	}
16759	if templateCopy.MaxNameLen == 0 {
16760		templateCopy.MaxNameLen = 64
16761	}
16762	return ServerECHConfig{ECHConfig: CreateECHConfig(&templateCopy), Key: secretKey}
16763}
16764
16765func addEncryptedClientHelloTests() {
16766	// echConfig's ConfigID should match the one used in ssl/test/fuzzer.h.
16767	echConfig := generateServerECHConfig(&ECHConfig{ConfigID: 42})
16768	echConfig1 := generateServerECHConfig(&ECHConfig{ConfigID: 43})
16769	echConfig2 := generateServerECHConfig(&ECHConfig{ConfigID: 44})
16770	echConfig3 := generateServerECHConfig(&ECHConfig{ConfigID: 45})
16771	echConfigRepeatID := generateServerECHConfig(&ECHConfig{ConfigID: 42})
16772
16773	echSecretCertificate := generateSingleCertChain(&x509.Certificate{
16774		SerialNumber: big.NewInt(57005),
16775		Subject: pkix.Name{
16776			CommonName: "test cert",
16777		},
16778		NotBefore:             time.Now().Add(-time.Hour),
16779		NotAfter:              time.Now().Add(time.Hour),
16780		DNSNames:              []string{"secret.example"},
16781		IsCA:                  true,
16782		BasicConstraintsValid: true,
16783	}, &rsa2048Key)
16784	echPublicCertificate := generateSingleCertChain(&x509.Certificate{
16785		SerialNumber: big.NewInt(57005),
16786		Subject: pkix.Name{
16787			CommonName: "test cert",
16788		},
16789		NotBefore:             time.Now().Add(-time.Hour),
16790		NotAfter:              time.Now().Add(time.Hour),
16791		DNSNames:              []string{"public.example"},
16792		IsCA:                  true,
16793		BasicConstraintsValid: true,
16794	}, &rsa2048Key)
16795	echLongNameCertificate := generateSingleCertChain(&x509.Certificate{
16796		SerialNumber: big.NewInt(57005),
16797		Subject: pkix.Name{
16798			CommonName: "test cert",
16799		},
16800		NotBefore:             time.Now().Add(-time.Hour),
16801		NotAfter:              time.Now().Add(time.Hour),
16802		DNSNames:              []string{"test0123456789.example"},
16803		IsCA:                  true,
16804		BasicConstraintsValid: true,
16805	}, &ecdsaP256Key)
16806
16807	for _, protocol := range []protocol{tls, quic} {
16808		prefix := protocol.String() + "-"
16809
16810		// There are two ClientHellos, so many of our tests have
16811		// HelloRetryRequest variations.
16812		for _, hrr := range []bool{false, true} {
16813			var suffix string
16814			var defaultCurves []CurveID
16815			if hrr {
16816				suffix = "-HelloRetryRequest"
16817				// Require a HelloRetryRequest for every curve.
16818				defaultCurves = []CurveID{}
16819			}
16820
16821			// Test the server can accept ECH.
16822			testCases = append(testCases, testCase{
16823				testType: serverTest,
16824				protocol: protocol,
16825				name:     prefix + "ECH-Server" + suffix,
16826				config: Config{
16827					ServerName:      "secret.example",
16828					ClientECHConfig: echConfig.ECHConfig,
16829					DefaultCurves:   defaultCurves,
16830				},
16831				resumeSession: true,
16832				flags: []string{
16833					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16834					"-ech-server-key", base64FlagValue(echConfig.Key),
16835					"-ech-is-retry-config", "1",
16836					"-expect-server-name", "secret.example",
16837					"-expect-ech-accept",
16838				},
16839				expectations: connectionExpectations{
16840					echAccepted: true,
16841				},
16842			})
16843
16844			// Test the server can accept ECH with a minimal ClientHelloOuter.
16845			// This confirms that the server does not unexpectedly pick up
16846			// fields from the wrong ClientHello.
16847			testCases = append(testCases, testCase{
16848				testType: serverTest,
16849				protocol: protocol,
16850				name:     prefix + "ECH-Server-MinimalClientHelloOuter" + suffix,
16851				config: Config{
16852					ServerName:      "secret.example",
16853					ClientECHConfig: echConfig.ECHConfig,
16854					DefaultCurves:   defaultCurves,
16855					Bugs: ProtocolBugs{
16856						MinimalClientHelloOuter: true,
16857					},
16858				},
16859				resumeSession: true,
16860				flags: []string{
16861					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16862					"-ech-server-key", base64FlagValue(echConfig.Key),
16863					"-ech-is-retry-config", "1",
16864					"-expect-server-name", "secret.example",
16865					"-expect-ech-accept",
16866				},
16867				expectations: connectionExpectations{
16868					echAccepted: true,
16869				},
16870			})
16871
16872			// Test that the server can decline ECH. In particular, it must send
16873			// retry configs.
16874			testCases = append(testCases, testCase{
16875				testType: serverTest,
16876				protocol: protocol,
16877				name:     prefix + "ECH-Server-Decline" + suffix,
16878				config: Config{
16879					ServerName:    "secret.example",
16880					DefaultCurves: defaultCurves,
16881					// The client uses an ECHConfig that the server does not understand
16882					// so we can observe which retry configs the server sends back.
16883					ClientECHConfig: echConfig.ECHConfig,
16884					Bugs: ProtocolBugs{
16885						OfferSessionInClientHelloOuter: true,
16886						ExpectECHRetryConfigs:          CreateECHConfigList(echConfig2.ECHConfig.Raw, echConfig3.ECHConfig.Raw),
16887					},
16888				},
16889				resumeSession: true,
16890				flags: []string{
16891					// Configure three ECHConfigs on the shim, only two of which
16892					// should be sent in retry configs.
16893					"-ech-server-config", base64FlagValue(echConfig1.ECHConfig.Raw),
16894					"-ech-server-key", base64FlagValue(echConfig1.Key),
16895					"-ech-is-retry-config", "0",
16896					"-ech-server-config", base64FlagValue(echConfig2.ECHConfig.Raw),
16897					"-ech-server-key", base64FlagValue(echConfig2.Key),
16898					"-ech-is-retry-config", "1",
16899					"-ech-server-config", base64FlagValue(echConfig3.ECHConfig.Raw),
16900					"-ech-server-key", base64FlagValue(echConfig3.Key),
16901					"-ech-is-retry-config", "1",
16902					"-expect-server-name", "public.example",
16903				},
16904			})
16905
16906			// Test that the server considers a ClientHelloInner indicating TLS
16907			// 1.2 to be a fatal error.
16908			testCases = append(testCases, testCase{
16909				testType: serverTest,
16910				protocol: protocol,
16911				name:     prefix + "ECH-Server-TLS12InInner" + suffix,
16912				config: Config{
16913					ServerName:      "secret.example",
16914					DefaultCurves:   defaultCurves,
16915					ClientECHConfig: echConfig.ECHConfig,
16916					Bugs: ProtocolBugs{
16917						AllowTLS12InClientHelloInner: true,
16918					},
16919				},
16920				flags: []string{
16921					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16922					"-ech-server-key", base64FlagValue(echConfig.Key),
16923					"-ech-is-retry-config", "1"},
16924				shouldFail:         true,
16925				expectedLocalError: "remote error: illegal parameter",
16926				expectedError:      ":INVALID_CLIENT_HELLO_INNER:",
16927			})
16928
16929			// When inner ECH extension is absent from the ClientHelloInner, the
16930			// server should fail the connection.
16931			testCases = append(testCases, testCase{
16932				testType: serverTest,
16933				protocol: protocol,
16934				name:     prefix + "ECH-Server-MissingECHInner" + suffix,
16935				config: Config{
16936					ServerName:      "secret.example",
16937					DefaultCurves:   defaultCurves,
16938					ClientECHConfig: echConfig.ECHConfig,
16939					Bugs: ProtocolBugs{
16940						OmitECHInner:       !hrr,
16941						OmitSecondECHInner: hrr,
16942					},
16943				},
16944				flags: []string{
16945					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16946					"-ech-server-key", base64FlagValue(echConfig.Key),
16947					"-ech-is-retry-config", "1",
16948				},
16949				shouldFail:         true,
16950				expectedLocalError: "remote error: illegal parameter",
16951				expectedError:      ":INVALID_CLIENT_HELLO_INNER:",
16952			})
16953
16954			// Test that the server can decode ech_outer_extensions.
16955			testCases = append(testCases, testCase{
16956				testType: serverTest,
16957				protocol: protocol,
16958				name:     prefix + "ECH-Server-OuterExtensions" + suffix,
16959				config: Config{
16960					ServerName:      "secret.example",
16961					DefaultCurves:   defaultCurves,
16962					ClientECHConfig: echConfig.ECHConfig,
16963					ECHOuterExtensions: []uint16{
16964						extensionKeyShare,
16965						extensionSupportedCurves,
16966						// Include a custom extension, to test that unrecognized
16967						// extensions are also decoded.
16968						extensionCustom,
16969					},
16970					Bugs: ProtocolBugs{
16971						CustomExtension:                    "test",
16972						OnlyCompressSecondClientHelloInner: hrr,
16973					},
16974				},
16975				flags: []string{
16976					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
16977					"-ech-server-key", base64FlagValue(echConfig.Key),
16978					"-ech-is-retry-config", "1",
16979					"-expect-server-name", "secret.example",
16980					"-expect-ech-accept",
16981				},
16982				expectations: connectionExpectations{
16983					echAccepted: true,
16984				},
16985			})
16986
16987			// Test that the server allows referenced ClientHelloOuter
16988			// extensions to be interleaved with other extensions. Only the
16989			// relative order must match.
16990			testCases = append(testCases, testCase{
16991				testType: serverTest,
16992				protocol: protocol,
16993				name:     prefix + "ECH-Server-OuterExtensions-Interleaved" + suffix,
16994				config: Config{
16995					ServerName:      "secret.example",
16996					DefaultCurves:   defaultCurves,
16997					ClientECHConfig: echConfig.ECHConfig,
16998					ECHOuterExtensions: []uint16{
16999						extensionKeyShare,
17000						extensionSupportedCurves,
17001						extensionCustom,
17002					},
17003					Bugs: ProtocolBugs{
17004						CustomExtension:                    "test",
17005						OnlyCompressSecondClientHelloInner: hrr,
17006						ECHOuterExtensionOrder: []uint16{
17007							extensionServerName,
17008							extensionKeyShare,
17009							extensionSupportedVersions,
17010							extensionPSKKeyExchangeModes,
17011							extensionSupportedCurves,
17012							extensionSignatureAlgorithms,
17013							extensionCustom,
17014						},
17015					},
17016				},
17017				flags: []string{
17018					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17019					"-ech-server-key", base64FlagValue(echConfig.Key),
17020					"-ech-is-retry-config", "1",
17021					"-expect-server-name", "secret.example",
17022					"-expect-ech-accept",
17023				},
17024				expectations: connectionExpectations{
17025					echAccepted: true,
17026				},
17027			})
17028
17029			// Test that the server rejects references to extensions in the
17030			// wrong order.
17031			testCases = append(testCases, testCase{
17032				testType: serverTest,
17033				protocol: protocol,
17034				name:     prefix + "ECH-Server-OuterExtensions-WrongOrder" + suffix,
17035				config: Config{
17036					ServerName:      "secret.example",
17037					DefaultCurves:   defaultCurves,
17038					ClientECHConfig: echConfig.ECHConfig,
17039					ECHOuterExtensions: []uint16{
17040						extensionKeyShare,
17041						extensionSupportedCurves,
17042					},
17043					Bugs: ProtocolBugs{
17044						CustomExtension:                    "test",
17045						OnlyCompressSecondClientHelloInner: hrr,
17046						ECHOuterExtensionOrder: []uint16{
17047							extensionSupportedCurves,
17048							extensionKeyShare,
17049						},
17050					},
17051				},
17052				flags: []string{
17053					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17054					"-ech-server-key", base64FlagValue(echConfig.Key),
17055					"-ech-is-retry-config", "1",
17056					"-expect-server-name", "secret.example",
17057				},
17058				shouldFail:         true,
17059				expectedLocalError: "remote error: illegal parameter",
17060				expectedError:      ":INVALID_OUTER_EXTENSION:",
17061			})
17062
17063			// Test that the server rejects duplicated values in ech_outer_extensions.
17064			// Besides causing the server to reconstruct an invalid ClientHelloInner
17065			// with duplicated extensions, this behavior would be vulnerable to DoS
17066			// attacks.
17067			testCases = append(testCases, testCase{
17068				testType: serverTest,
17069				protocol: protocol,
17070				name:     prefix + "ECH-Server-OuterExtensions-Duplicate" + suffix,
17071				config: Config{
17072					ServerName:      "secret.example",
17073					DefaultCurves:   defaultCurves,
17074					ClientECHConfig: echConfig.ECHConfig,
17075					ECHOuterExtensions: []uint16{
17076						extensionSupportedCurves,
17077						extensionSupportedCurves,
17078					},
17079					Bugs: ProtocolBugs{
17080						OnlyCompressSecondClientHelloInner: hrr,
17081						// Don't duplicate the extension in ClientHelloOuter.
17082						ECHOuterExtensionOrder: []uint16{
17083							extensionSupportedCurves,
17084						},
17085					},
17086				},
17087				flags: []string{
17088					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17089					"-ech-server-key", base64FlagValue(echConfig.Key),
17090					"-ech-is-retry-config", "1",
17091				},
17092				shouldFail:         true,
17093				expectedLocalError: "remote error: illegal parameter",
17094				expectedError:      ":INVALID_OUTER_EXTENSION:",
17095			})
17096
17097			// Test that the server rejects references to missing extensions in
17098			// ech_outer_extensions.
17099			testCases = append(testCases, testCase{
17100				testType: serverTest,
17101				protocol: protocol,
17102				name:     prefix + "ECH-Server-OuterExtensions-Missing" + suffix,
17103				config: Config{
17104					ServerName:      "secret.example",
17105					DefaultCurves:   defaultCurves,
17106					ClientECHConfig: echConfig.ECHConfig,
17107					ECHOuterExtensions: []uint16{
17108						extensionCustom,
17109					},
17110					Bugs: ProtocolBugs{
17111						OnlyCompressSecondClientHelloInner: hrr,
17112					},
17113				},
17114				flags: []string{
17115					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17116					"-ech-server-key", base64FlagValue(echConfig.Key),
17117					"-ech-is-retry-config", "1",
17118					"-expect-server-name", "secret.example",
17119					"-expect-ech-accept",
17120				},
17121				shouldFail:         true,
17122				expectedLocalError: "remote error: illegal parameter",
17123				expectedError:      ":INVALID_OUTER_EXTENSION:",
17124			})
17125
17126			// Test that the server rejects a references to the ECH extension in
17127			// ech_outer_extensions. The ECH extension is not authenticated in the
17128			// AAD and would result in an invalid ClientHelloInner.
17129			testCases = append(testCases, testCase{
17130				testType: serverTest,
17131				protocol: protocol,
17132				name:     prefix + "ECH-Server-OuterExtensions-SelfReference" + suffix,
17133				config: Config{
17134					ServerName:      "secret.example",
17135					DefaultCurves:   defaultCurves,
17136					ClientECHConfig: echConfig.ECHConfig,
17137					ECHOuterExtensions: []uint16{
17138						extensionEncryptedClientHello,
17139					},
17140					Bugs: ProtocolBugs{
17141						OnlyCompressSecondClientHelloInner: hrr,
17142					},
17143				},
17144				flags: []string{
17145					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17146					"-ech-server-key", base64FlagValue(echConfig.Key),
17147					"-ech-is-retry-config", "1",
17148				},
17149				shouldFail:         true,
17150				expectedLocalError: "remote error: illegal parameter",
17151				expectedError:      ":INVALID_OUTER_EXTENSION:",
17152			})
17153
17154			// Test the message callback is correctly reported with ECH.
17155			clientAndServerHello := "read hs 1\nread clienthelloinner\nwrite hs 2\n"
17156			expectMsgCallback := clientAndServerHello + "write ccs\n"
17157			if hrr {
17158				expectMsgCallback += clientAndServerHello
17159			}
17160			// EncryptedExtensions onwards.
17161			expectMsgCallback += `write hs 8
17162write hs 11
17163write hs 15
17164write hs 20
17165read hs 20
17166write hs 4
17167write hs 4
17168`
17169			testCases = append(testCases, testCase{
17170				testType: serverTest,
17171				protocol: protocol,
17172				name:     prefix + "ECH-Server-MessageCallback" + suffix,
17173				config: Config{
17174					ServerName:      "secret.example",
17175					ClientECHConfig: echConfig.ECHConfig,
17176					DefaultCurves:   defaultCurves,
17177					Bugs: ProtocolBugs{
17178						NoCloseNotify: true, // Align QUIC and TCP traces.
17179					},
17180				},
17181				flags: []string{
17182					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17183					"-ech-server-key", base64FlagValue(echConfig.Key),
17184					"-ech-is-retry-config", "1",
17185					"-expect-ech-accept",
17186					"-expect-msg-callback", expectMsgCallback,
17187				},
17188				expectations: connectionExpectations{
17189					echAccepted: true,
17190				},
17191			})
17192		}
17193
17194		// Test that ECH, which runs before an async early callback, interacts
17195		// correctly in the state machine.
17196		testCases = append(testCases, testCase{
17197			testType: serverTest,
17198			protocol: protocol,
17199			name:     prefix + "ECH-Server-AsyncEarlyCallback",
17200			config: Config{
17201				ServerName:      "secret.example",
17202				ClientECHConfig: echConfig.ECHConfig,
17203			},
17204			flags: []string{
17205				"-async",
17206				"-use-early-callback",
17207				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17208				"-ech-server-key", base64FlagValue(echConfig.Key),
17209				"-ech-is-retry-config", "1",
17210				"-expect-server-name", "secret.example",
17211				"-expect-ech-accept",
17212			},
17213			expectations: connectionExpectations{
17214				echAccepted: true,
17215			},
17216		})
17217
17218		// Test ECH-enabled server with two ECHConfigs can decrypt client's ECH when
17219		// it uses the second ECHConfig.
17220		testCases = append(testCases, testCase{
17221			testType: serverTest,
17222			protocol: protocol,
17223			name:     prefix + "ECH-Server-SecondECHConfig",
17224			config: Config{
17225				ServerName:      "secret.example",
17226				ClientECHConfig: echConfig1.ECHConfig,
17227			},
17228			flags: []string{
17229				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17230				"-ech-server-key", base64FlagValue(echConfig.Key),
17231				"-ech-is-retry-config", "1",
17232				"-ech-server-config", base64FlagValue(echConfig1.ECHConfig.Raw),
17233				"-ech-server-key", base64FlagValue(echConfig1.Key),
17234				"-ech-is-retry-config", "1",
17235				"-expect-server-name", "secret.example",
17236				"-expect-ech-accept",
17237			},
17238			expectations: connectionExpectations{
17239				echAccepted: true,
17240			},
17241		})
17242
17243		// Test ECH-enabled server with two ECHConfigs that have the same config
17244		// ID can decrypt client's ECH when it uses the second ECHConfig.
17245		testCases = append(testCases, testCase{
17246			testType: serverTest,
17247			protocol: protocol,
17248			name:     prefix + "ECH-Server-RepeatedConfigID",
17249			config: Config{
17250				ServerName:      "secret.example",
17251				ClientECHConfig: echConfigRepeatID.ECHConfig,
17252			},
17253			flags: []string{
17254				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17255				"-ech-server-key", base64FlagValue(echConfig.Key),
17256				"-ech-is-retry-config", "1",
17257				"-ech-server-config", base64FlagValue(echConfigRepeatID.ECHConfig.Raw),
17258				"-ech-server-key", base64FlagValue(echConfigRepeatID.Key),
17259				"-ech-is-retry-config", "1",
17260				"-expect-server-name", "secret.example",
17261				"-expect-ech-accept",
17262			},
17263			expectations: connectionExpectations{
17264				echAccepted: true,
17265			},
17266		})
17267
17268		// Test all supported ECH cipher suites.
17269		for i, cipher := range echCiphers {
17270			otherCipher := echCiphers[(i+1)%len(echCiphers)]
17271
17272			// Test the ECH server can handle the specified cipher.
17273			testCases = append(testCases, testCase{
17274				testType: serverTest,
17275				protocol: protocol,
17276				name:     prefix + "ECH-Server-Cipher-" + cipher.name,
17277				config: Config{
17278					ServerName:      "secret.example",
17279					ClientECHConfig: echConfig.ECHConfig,
17280					ECHCipherSuites: []HPKECipherSuite{cipher.cipher},
17281				},
17282				flags: []string{
17283					"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17284					"-ech-server-key", base64FlagValue(echConfig.Key),
17285					"-ech-is-retry-config", "1",
17286					"-expect-server-name", "secret.example",
17287					"-expect-ech-accept",
17288				},
17289				expectations: connectionExpectations{
17290					echAccepted: true,
17291				},
17292			})
17293
17294			// Test that client can offer the specified cipher and skip over
17295			// unrecognized ones.
17296			cipherConfig := generateServerECHConfig(&ECHConfig{
17297				ConfigID: 42,
17298				CipherSuites: []HPKECipherSuite{
17299					{KDF: 0x1111, AEAD: 0x2222},
17300					{KDF: cipher.cipher.KDF, AEAD: 0x2222},
17301					{KDF: 0x1111, AEAD: cipher.cipher.AEAD},
17302					cipher.cipher,
17303				},
17304			})
17305			testCases = append(testCases, testCase{
17306				testType: clientTest,
17307				protocol: protocol,
17308				name:     prefix + "ECH-Client-Cipher-" + cipher.name,
17309				config: Config{
17310					ServerECHConfigs: []ServerECHConfig{cipherConfig},
17311					Credential:       &echSecretCertificate,
17312				},
17313				flags: []string{
17314					"-ech-config-list", base64FlagValue(CreateECHConfigList(cipherConfig.ECHConfig.Raw)),
17315					"-host-name", "secret.example",
17316					"-expect-ech-accept",
17317				},
17318				expectations: connectionExpectations{
17319					echAccepted: true,
17320				},
17321			})
17322
17323			// Test that the ECH server rejects the specified cipher if not
17324			// listed in its ECHConfig.
17325			otherCipherConfig := generateServerECHConfig(&ECHConfig{
17326				ConfigID:     42,
17327				CipherSuites: []HPKECipherSuite{otherCipher.cipher},
17328			})
17329			testCases = append(testCases, testCase{
17330				testType: serverTest,
17331				protocol: protocol,
17332				name:     prefix + "ECH-Server-DisabledCipher-" + cipher.name,
17333				config: Config{
17334					ServerName:      "secret.example",
17335					ClientECHConfig: echConfig.ECHConfig,
17336					ECHCipherSuites: []HPKECipherSuite{cipher.cipher},
17337					Bugs: ProtocolBugs{
17338						ExpectECHRetryConfigs: CreateECHConfigList(otherCipherConfig.ECHConfig.Raw),
17339					},
17340				},
17341				flags: []string{
17342					"-ech-server-config", base64FlagValue(otherCipherConfig.ECHConfig.Raw),
17343					"-ech-server-key", base64FlagValue(otherCipherConfig.Key),
17344					"-ech-is-retry-config", "1",
17345					"-expect-server-name", "public.example",
17346				},
17347			})
17348		}
17349
17350		// Test that the ECH server handles a short enc value by falling back to
17351		// ClientHelloOuter.
17352		testCases = append(testCases, testCase{
17353			testType: serverTest,
17354			protocol: protocol,
17355			name:     prefix + "ECH-Server-ShortEnc",
17356			config: Config{
17357				ServerName:      "secret.example",
17358				ClientECHConfig: echConfig.ECHConfig,
17359				Bugs: ProtocolBugs{
17360					ExpectECHRetryConfigs: CreateECHConfigList(echConfig.ECHConfig.Raw),
17361					TruncateClientECHEnc:  true,
17362				},
17363			},
17364			flags: []string{
17365				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17366				"-ech-server-key", base64FlagValue(echConfig.Key),
17367				"-ech-is-retry-config", "1",
17368				"-expect-server-name", "public.example",
17369			},
17370		})
17371
17372		// Test that the server handles decryption failure by falling back to
17373		// ClientHelloOuter.
17374		testCases = append(testCases, testCase{
17375			testType: serverTest,
17376			protocol: protocol,
17377			name:     prefix + "ECH-Server-CorruptEncryptedClientHello",
17378			config: Config{
17379				ServerName:      "secret.example",
17380				ClientECHConfig: echConfig.ECHConfig,
17381				Bugs: ProtocolBugs{
17382					ExpectECHRetryConfigs:       CreateECHConfigList(echConfig.ECHConfig.Raw),
17383					CorruptEncryptedClientHello: true,
17384				},
17385			},
17386			flags: []string{
17387				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17388				"-ech-server-key", base64FlagValue(echConfig.Key),
17389				"-ech-is-retry-config", "1",
17390			},
17391		})
17392
17393		// Test that the server treats decryption failure in the second
17394		// ClientHello as fatal.
17395		testCases = append(testCases, testCase{
17396			testType: serverTest,
17397			protocol: protocol,
17398			name:     prefix + "ECH-Server-CorruptSecondEncryptedClientHello",
17399			config: Config{
17400				ServerName:      "secret.example",
17401				ClientECHConfig: echConfig.ECHConfig,
17402				// Force a HelloRetryRequest.
17403				DefaultCurves: []CurveID{},
17404				Bugs: ProtocolBugs{
17405					CorruptSecondEncryptedClientHello: true,
17406				},
17407			},
17408			flags: []string{
17409				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17410				"-ech-server-key", base64FlagValue(echConfig.Key),
17411				"-ech-is-retry-config", "1",
17412			},
17413			shouldFail:         true,
17414			expectedError:      ":DECRYPTION_FAILED:",
17415			expectedLocalError: "remote error: error decrypting message",
17416		})
17417
17418		// Test that the server treats a missing second ECH extension as fatal.
17419		testCases = append(testCases, testCase{
17420			testType: serverTest,
17421			protocol: protocol,
17422			name:     prefix + "ECH-Server-OmitSecondEncryptedClientHello",
17423			config: Config{
17424				ServerName:      "secret.example",
17425				ClientECHConfig: echConfig.ECHConfig,
17426				// Force a HelloRetryRequest.
17427				DefaultCurves: []CurveID{},
17428				Bugs: ProtocolBugs{
17429					OmitSecondEncryptedClientHello: true,
17430				},
17431			},
17432			flags: []string{
17433				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17434				"-ech-server-key", base64FlagValue(echConfig.Key),
17435				"-ech-is-retry-config", "1",
17436			},
17437			shouldFail:         true,
17438			expectedError:      ":MISSING_EXTENSION:",
17439			expectedLocalError: "remote error: missing extension",
17440		})
17441
17442		// Test that the server treats a mismatched config ID in the second ClientHello as fatal.
17443		testCases = append(testCases, testCase{
17444			testType: serverTest,
17445			protocol: protocol,
17446			name:     prefix + "ECH-Server-DifferentConfigIDSecondClientHello",
17447			config: Config{
17448				ServerName:      "secret.example",
17449				ClientECHConfig: echConfig.ECHConfig,
17450				// Force a HelloRetryRequest.
17451				DefaultCurves: []CurveID{},
17452				Bugs: ProtocolBugs{
17453					CorruptSecondEncryptedClientHelloConfigID: true,
17454				},
17455			},
17456			flags: []string{
17457				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17458				"-ech-server-key", base64FlagValue(echConfig.Key),
17459				"-ech-is-retry-config", "1",
17460			},
17461			shouldFail:         true,
17462			expectedError:      ":DECODE_ERROR:",
17463			expectedLocalError: "remote error: illegal parameter",
17464		})
17465
17466		// Test early data works with ECH, in both accept and reject cases.
17467		testCases = append(testCases, testCase{
17468			testType: serverTest,
17469			protocol: protocol,
17470			name:     prefix + "ECH-Server-EarlyData",
17471			config: Config{
17472				ServerName:      "secret.example",
17473				ClientECHConfig: echConfig.ECHConfig,
17474			},
17475			resumeSession: true,
17476			earlyData:     true,
17477			flags: []string{
17478				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17479				"-ech-server-key", base64FlagValue(echConfig.Key),
17480				"-ech-is-retry-config", "1",
17481				"-expect-ech-accept",
17482			},
17483			expectations: connectionExpectations{
17484				echAccepted: true,
17485			},
17486		})
17487		testCases = append(testCases, testCase{
17488			testType: serverTest,
17489			protocol: protocol,
17490			name:     prefix + "ECH-Server-EarlyDataRejected",
17491			config: Config{
17492				ServerName:      "secret.example",
17493				ClientECHConfig: echConfig.ECHConfig,
17494				Bugs: ProtocolBugs{
17495					// Cause the server to reject 0-RTT with a bad ticket age.
17496					SendTicketAge: 1 * time.Hour,
17497				},
17498			},
17499			resumeSession:           true,
17500			earlyData:               true,
17501			expectEarlyDataRejected: true,
17502			flags: []string{
17503				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17504				"-ech-server-key", base64FlagValue(echConfig.Key),
17505				"-ech-is-retry-config", "1",
17506				"-expect-ech-accept",
17507			},
17508			expectations: connectionExpectations{
17509				echAccepted: true,
17510			},
17511		})
17512
17513		// Test servers with ECH disabled correctly ignore the extension and
17514		// handshake with the ClientHelloOuter.
17515		testCases = append(testCases, testCase{
17516			testType: serverTest,
17517			protocol: protocol,
17518			name:     prefix + "ECH-Server-Disabled",
17519			config: Config{
17520				ServerName:      "secret.example",
17521				ClientECHConfig: echConfig.ECHConfig,
17522			},
17523			flags: []string{
17524				"-expect-server-name", "public.example",
17525			},
17526		})
17527
17528		// Test that ECH can be used with client certificates. In particular,
17529		// the name override logic should not interfere with the server.
17530		// Test the server can accept ECH.
17531		testCases = append(testCases, testCase{
17532			testType: serverTest,
17533			protocol: protocol,
17534			name:     prefix + "ECH-Server-ClientAuth",
17535			config: Config{
17536				Credential:      &rsaCertificate,
17537				ClientECHConfig: echConfig.ECHConfig,
17538			},
17539			flags: []string{
17540				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17541				"-ech-server-key", base64FlagValue(echConfig.Key),
17542				"-ech-is-retry-config", "1",
17543				"-expect-ech-accept",
17544				"-require-any-client-certificate",
17545			},
17546			expectations: connectionExpectations{
17547				echAccepted: true,
17548			},
17549		})
17550		testCases = append(testCases, testCase{
17551			testType: serverTest,
17552			protocol: protocol,
17553			name:     prefix + "ECH-Server-Decline-ClientAuth",
17554			config: Config{
17555				Credential:      &rsaCertificate,
17556				ClientECHConfig: echConfig.ECHConfig,
17557				Bugs: ProtocolBugs{
17558					ExpectECHRetryConfigs: CreateECHConfigList(echConfig1.ECHConfig.Raw),
17559				},
17560			},
17561			flags: []string{
17562				"-ech-server-config", base64FlagValue(echConfig1.ECHConfig.Raw),
17563				"-ech-server-key", base64FlagValue(echConfig1.Key),
17564				"-ech-is-retry-config", "1",
17565				"-require-any-client-certificate",
17566			},
17567		})
17568
17569		// Test that the server accepts padding.
17570		testCases = append(testCases, testCase{
17571			testType: serverTest,
17572			protocol: protocol,
17573			name:     prefix + "ECH-Server-Padding",
17574			config: Config{
17575				ClientECHConfig: echConfig.ECHConfig,
17576				Bugs: ProtocolBugs{
17577					ClientECHPadding: 10,
17578				},
17579			},
17580			flags: []string{
17581				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17582				"-ech-server-key", base64FlagValue(echConfig.Key),
17583				"-ech-is-retry-config", "1",
17584				"-expect-ech-accept",
17585			},
17586			expectations: connectionExpectations{
17587				echAccepted: true,
17588			},
17589		})
17590
17591		// Test that the server rejects bad padding.
17592		testCases = append(testCases, testCase{
17593			testType: serverTest,
17594			protocol: protocol,
17595			name:     prefix + "ECH-Server-BadPadding",
17596			config: Config{
17597				ClientECHConfig: echConfig.ECHConfig,
17598				Bugs: ProtocolBugs{
17599					ClientECHPadding:    10,
17600					BadClientECHPadding: true,
17601				},
17602			},
17603			flags: []string{
17604				"-ech-server-config", base64FlagValue(echConfig.ECHConfig.Raw),
17605				"-ech-server-key", base64FlagValue(echConfig.Key),
17606				"-ech-is-retry-config", "1",
17607				"-expect-ech-accept",
17608			},
17609			expectations: connectionExpectations{
17610				echAccepted: true,
17611			},
17612			shouldFail:         true,
17613			expectedError:      ":DECODE_ERROR",
17614			expectedLocalError: "remote error: illegal parameter",
17615		})
17616
17617		// Test the client's behavior when the server ignores ECH GREASE.
17618		testCases = append(testCases, testCase{
17619			testType: clientTest,
17620			protocol: protocol,
17621			name:     prefix + "ECH-GREASE-Client-TLS13",
17622			config: Config{
17623				MinVersion: VersionTLS13,
17624				MaxVersion: VersionTLS13,
17625				Bugs: ProtocolBugs{
17626					ExpectClientECH: true,
17627				},
17628			},
17629			flags: []string{"-enable-ech-grease"},
17630		})
17631
17632		// Test the client's ECH GREASE behavior when responding to server's
17633		// HelloRetryRequest. This test implicitly checks that the first and second
17634		// ClientHello messages have identical ECH extensions.
17635		testCases = append(testCases, testCase{
17636			testType: clientTest,
17637			protocol: protocol,
17638			name:     prefix + "ECH-GREASE-Client-TLS13-HelloRetryRequest",
17639			config: Config{
17640				MaxVersion: VersionTLS13,
17641				MinVersion: VersionTLS13,
17642				// P-384 requires a HelloRetryRequest against BoringSSL's default
17643				// configuration. Assert this with ExpectMissingKeyShare.
17644				CurvePreferences: []CurveID{CurveP384},
17645				Bugs: ProtocolBugs{
17646					ExpectMissingKeyShare: true,
17647					ExpectClientECH:       true,
17648				},
17649			},
17650			flags: []string{"-enable-ech-grease", "-expect-hrr"},
17651		})
17652
17653		unsupportedVersion := []byte{
17654			// version
17655			0xba, 0xdd,
17656			// length
17657			0x00, 0x05,
17658			// contents
17659			0x05, 0x04, 0x03, 0x02, 0x01,
17660		}
17661
17662		// Test that the client accepts a well-formed encrypted_client_hello
17663		// extension in response to ECH GREASE. The response includes one ECHConfig
17664		// with a supported version and one with an unsupported version.
17665		testCases = append(testCases, testCase{
17666			testType: clientTest,
17667			protocol: protocol,
17668			name:     prefix + "ECH-GREASE-Client-TLS13-Retry-Configs",
17669			config: Config{
17670				MinVersion: VersionTLS13,
17671				MaxVersion: VersionTLS13,
17672				Bugs: ProtocolBugs{
17673					ExpectClientECH: true,
17674					// Include an additional well-formed ECHConfig with an
17675					// unsupported version. This ensures the client can skip
17676					// unsupported configs.
17677					SendECHRetryConfigs: CreateECHConfigList(echConfig.ECHConfig.Raw, unsupportedVersion),
17678				},
17679			},
17680			flags: []string{"-enable-ech-grease"},
17681		})
17682
17683		// TLS 1.2 ServerHellos cannot contain retry configs.
17684		if protocol != quic {
17685			testCases = append(testCases, testCase{
17686				testType: clientTest,
17687				protocol: protocol,
17688				name:     prefix + "ECH-GREASE-Client-TLS12-RejectRetryConfigs",
17689				config: Config{
17690					MinVersion:       VersionTLS12,
17691					MaxVersion:       VersionTLS12,
17692					ServerECHConfigs: []ServerECHConfig{echConfig},
17693					Bugs: ProtocolBugs{
17694						ExpectClientECH:           true,
17695						AlwaysSendECHRetryConfigs: true,
17696					},
17697				},
17698				flags:              []string{"-enable-ech-grease"},
17699				shouldFail:         true,
17700				expectedLocalError: "remote error: unsupported extension",
17701				expectedError:      ":UNEXPECTED_EXTENSION:",
17702			})
17703			testCases = append(testCases, testCase{
17704				testType: clientTest,
17705				protocol: protocol,
17706				name:     prefix + "ECH-Client-TLS12-RejectRetryConfigs",
17707				config: Config{
17708					MinVersion:       VersionTLS12,
17709					MaxVersion:       VersionTLS12,
17710					ServerECHConfigs: []ServerECHConfig{echConfig},
17711					Bugs: ProtocolBugs{
17712						ExpectClientECH:           true,
17713						AlwaysSendECHRetryConfigs: true,
17714					},
17715				},
17716				flags: []string{
17717					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig1.ECHConfig.Raw)),
17718				},
17719				shouldFail:         true,
17720				expectedLocalError: "remote error: unsupported extension",
17721				expectedError:      ":UNEXPECTED_EXTENSION:",
17722			})
17723		}
17724
17725		// Retry configs must be rejected when ECH is accepted.
17726		testCases = append(testCases, testCase{
17727			testType: clientTest,
17728			protocol: protocol,
17729			name:     prefix + "ECH-Client-Accept-RejectRetryConfigs",
17730			config: Config{
17731				ServerECHConfigs: []ServerECHConfig{echConfig},
17732				Bugs: ProtocolBugs{
17733					ExpectClientECH:           true,
17734					AlwaysSendECHRetryConfigs: true,
17735				},
17736			},
17737			flags: []string{
17738				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17739			},
17740			shouldFail:         true,
17741			expectedLocalError: "remote error: unsupported extension",
17742			expectedError:      ":UNEXPECTED_EXTENSION:",
17743		})
17744
17745		// Unsolicited ECH HelloRetryRequest extensions should be rejected.
17746		testCases = append(testCases, testCase{
17747			testType: clientTest,
17748			protocol: protocol,
17749			name:     prefix + "ECH-Client-UnsolictedHRRExtension",
17750			config: Config{
17751				ServerECHConfigs: []ServerECHConfig{echConfig},
17752				CurvePreferences: []CurveID{CurveP384},
17753				Bugs: ProtocolBugs{
17754					AlwaysSendECHHelloRetryRequest: true,
17755					ExpectMissingKeyShare:          true, // Check we triggered HRR.
17756				},
17757			},
17758			shouldFail:         true,
17759			expectedLocalError: "remote error: unsupported extension",
17760			expectedError:      ":UNEXPECTED_EXTENSION:",
17761		})
17762
17763		// GREASE should ignore ECH HelloRetryRequest extensions.
17764		testCases = append(testCases, testCase{
17765			testType: clientTest,
17766			protocol: protocol,
17767			name:     prefix + "ECH-Client-GREASE-IgnoreHRRExtension",
17768			config: Config{
17769				CurvePreferences: []CurveID{CurveP384},
17770				Bugs: ProtocolBugs{
17771					AlwaysSendECHHelloRetryRequest: true,
17772					ExpectMissingKeyShare:          true, // Check we triggered HRR.
17773				},
17774			},
17775			flags: []string{"-enable-ech-grease"},
17776		})
17777
17778		// Random ECH HelloRetryRequest extensions also signal ECH reject.
17779		testCases = append(testCases, testCase{
17780			testType: clientTest,
17781			protocol: protocol,
17782			name:     prefix + "ECH-Client-Reject-RandomHRRExtension",
17783			config: Config{
17784				CurvePreferences: []CurveID{CurveP384},
17785				Bugs: ProtocolBugs{
17786					AlwaysSendECHHelloRetryRequest: true,
17787					ExpectMissingKeyShare:          true, // Check we triggered HRR.
17788				},
17789			},
17790			flags: []string{
17791				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17792			},
17793			shouldFail:         true,
17794			expectedLocalError: "remote error: ECH required",
17795			expectedError:      ":ECH_REJECTED:",
17796		})
17797
17798		// Test that the client aborts with a decode_error alert when it receives a
17799		// syntactically-invalid encrypted_client_hello extension from the server.
17800		testCases = append(testCases, testCase{
17801			testType: clientTest,
17802			protocol: protocol,
17803			name:     prefix + "ECH-GREASE-Client-TLS13-Invalid-Retry-Configs",
17804			config: Config{
17805				MinVersion: VersionTLS13,
17806				MaxVersion: VersionTLS13,
17807				Bugs: ProtocolBugs{
17808					ExpectClientECH:     true,
17809					SendECHRetryConfigs: []byte{0xba, 0xdd, 0xec, 0xcc},
17810				},
17811			},
17812			flags:              []string{"-enable-ech-grease"},
17813			shouldFail:         true,
17814			expectedLocalError: "remote error: error decoding message",
17815			expectedError:      ":ERROR_PARSING_EXTENSION:",
17816		})
17817
17818		// Test that the server responds to an inner ECH extension with the
17819		// acceptance confirmation.
17820		testCases = append(testCases, testCase{
17821			testType: serverTest,
17822			protocol: protocol,
17823			name:     prefix + "ECH-Server-ECHInner",
17824			config: Config{
17825				MinVersion: VersionTLS13,
17826				MaxVersion: VersionTLS13,
17827				Bugs: ProtocolBugs{
17828					AlwaysSendECHInner: true,
17829				},
17830			},
17831			resumeSession: true,
17832		})
17833		testCases = append(testCases, testCase{
17834			testType: serverTest,
17835			protocol: protocol,
17836			name:     prefix + "ECH-Server-ECHInner-HelloRetryRequest",
17837			config: Config{
17838				MinVersion: VersionTLS13,
17839				MaxVersion: VersionTLS13,
17840				// Force a HelloRetryRequest.
17841				DefaultCurves: []CurveID{},
17842				Bugs: ProtocolBugs{
17843					AlwaysSendECHInner: true,
17844				},
17845			},
17846			resumeSession: true,
17847		})
17848
17849		// Test that server fails the handshake when it sees a non-empty
17850		// inner ECH extension.
17851		testCases = append(testCases, testCase{
17852			testType: serverTest,
17853			protocol: protocol,
17854			name:     prefix + "ECH-Server-ECHInner-NotEmpty",
17855			config: Config{
17856				MinVersion: VersionTLS13,
17857				MaxVersion: VersionTLS13,
17858				Bugs: ProtocolBugs{
17859					AlwaysSendECHInner:  true,
17860					SendInvalidECHInner: []byte{42, 42, 42},
17861				},
17862			},
17863			shouldFail:         true,
17864			expectedLocalError: "remote error: error decoding message",
17865			expectedError:      ":ERROR_PARSING_EXTENSION:",
17866		})
17867
17868		// Test that a TLS 1.3 server that receives an inner ECH extension can
17869		// negotiate TLS 1.2 without clobbering the downgrade signal.
17870		if protocol != quic {
17871			testCases = append(testCases, testCase{
17872				testType: serverTest,
17873				protocol: protocol,
17874				name:     prefix + "ECH-Server-ECHInner-Absent-TLS12",
17875				config: Config{
17876					MinVersion: VersionTLS12,
17877					MaxVersion: VersionTLS13,
17878					Bugs: ProtocolBugs{
17879						// Omit supported_versions extension so the server negotiates
17880						// TLS 1.2.
17881						OmitSupportedVersions: true,
17882						AlwaysSendECHInner:    true,
17883					},
17884				},
17885				// Check that the client sees the TLS 1.3 downgrade signal in
17886				// ServerHello.random.
17887				shouldFail:         true,
17888				expectedLocalError: "tls: downgrade from TLS 1.3 detected",
17889			})
17890		}
17891
17892		// Test the client can negotiate ECH, with and without HelloRetryRequest.
17893		testCases = append(testCases, testCase{
17894			testType: clientTest,
17895			protocol: protocol,
17896			name:     prefix + "ECH-Client",
17897			config: Config{
17898				MinVersion:       VersionTLS13,
17899				MaxVersion:       VersionTLS13,
17900				ServerECHConfigs: []ServerECHConfig{echConfig},
17901				Bugs: ProtocolBugs{
17902					ExpectServerName:      "secret.example",
17903					ExpectOuterServerName: "public.example",
17904				},
17905				Credential: &echSecretCertificate,
17906			},
17907			flags: []string{
17908				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17909				"-host-name", "secret.example",
17910				"-expect-ech-accept",
17911			},
17912			resumeSession: true,
17913			expectations:  connectionExpectations{echAccepted: true},
17914		})
17915		testCases = append(testCases, testCase{
17916			testType: clientTest,
17917			protocol: protocol,
17918			name:     prefix + "ECH-Client-HelloRetryRequest",
17919			config: Config{
17920				MinVersion:       VersionTLS13,
17921				MaxVersion:       VersionTLS13,
17922				CurvePreferences: []CurveID{CurveP384},
17923				ServerECHConfigs: []ServerECHConfig{echConfig},
17924				Bugs: ProtocolBugs{
17925					ExpectServerName:      "secret.example",
17926					ExpectOuterServerName: "public.example",
17927					ExpectMissingKeyShare: true, // Check we triggered HRR.
17928				},
17929				Credential: &echSecretCertificate,
17930			},
17931			resumeSession: true,
17932			flags: []string{
17933				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17934				"-host-name", "secret.example",
17935				"-expect-ech-accept",
17936				"-expect-hrr", // Check we triggered HRR.
17937			},
17938			expectations: connectionExpectations{echAccepted: true},
17939		})
17940
17941		// Test the client can negotiate ECH with early data.
17942		testCases = append(testCases, testCase{
17943			testType: clientTest,
17944			protocol: protocol,
17945			name:     prefix + "ECH-Client-EarlyData",
17946			config: Config{
17947				MinVersion:       VersionTLS13,
17948				MaxVersion:       VersionTLS13,
17949				ServerECHConfigs: []ServerECHConfig{echConfig},
17950				Bugs: ProtocolBugs{
17951					ExpectServerName: "secret.example",
17952				},
17953				Credential: &echSecretCertificate,
17954			},
17955			flags: []string{
17956				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17957				"-host-name", "secret.example",
17958				"-expect-ech-accept",
17959			},
17960			resumeSession: true,
17961			earlyData:     true,
17962			expectations:  connectionExpectations{echAccepted: true},
17963		})
17964		testCases = append(testCases, testCase{
17965			testType: clientTest,
17966			protocol: protocol,
17967			name:     prefix + "ECH-Client-EarlyDataRejected",
17968			config: Config{
17969				MinVersion:       VersionTLS13,
17970				MaxVersion:       VersionTLS13,
17971				ServerECHConfigs: []ServerECHConfig{echConfig},
17972				Bugs: ProtocolBugs{
17973					ExpectServerName:      "secret.example",
17974					AlwaysRejectEarlyData: true,
17975				},
17976				Credential: &echSecretCertificate,
17977			},
17978			flags: []string{
17979				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
17980				"-host-name", "secret.example",
17981				"-expect-ech-accept",
17982			},
17983			resumeSession:           true,
17984			earlyData:               true,
17985			expectEarlyDataRejected: true,
17986			expectations:            connectionExpectations{echAccepted: true},
17987		})
17988
17989		if protocol != quic {
17990			// Test that an ECH client does not offer a TLS 1.2 session.
17991			testCases = append(testCases, testCase{
17992				testType: clientTest,
17993				protocol: protocol,
17994				name:     prefix + "ECH-Client-TLS12SessionID",
17995				config: Config{
17996					MaxVersion:             VersionTLS12,
17997					SessionTicketsDisabled: true,
17998				},
17999				resumeConfig: &Config{
18000					ServerECHConfigs: []ServerECHConfig{echConfig},
18001					Bugs: ProtocolBugs{
18002						ExpectNoTLS12Session: true,
18003					},
18004				},
18005				flags: []string{
18006					"-on-resume-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18007					"-on-resume-expect-ech-accept",
18008				},
18009				resumeSession:        true,
18010				expectResumeRejected: true,
18011				resumeExpectations:   &connectionExpectations{echAccepted: true},
18012			})
18013			testCases = append(testCases, testCase{
18014				testType: clientTest,
18015				protocol: protocol,
18016				name:     prefix + "ECH-Client-TLS12SessionTicket",
18017				config: Config{
18018					MaxVersion: VersionTLS12,
18019				},
18020				resumeConfig: &Config{
18021					ServerECHConfigs: []ServerECHConfig{echConfig},
18022					Bugs: ProtocolBugs{
18023						ExpectNoTLS12Session: true,
18024					},
18025				},
18026				flags: []string{
18027					"-on-resume-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18028					"-on-resume-expect-ech-accept",
18029				},
18030				resumeSession:        true,
18031				expectResumeRejected: true,
18032				resumeExpectations:   &connectionExpectations{echAccepted: true},
18033			})
18034		}
18035
18036		// ClientHelloInner should not include NPN, which is a TLS 1.2-only
18037		// extensions. The Go server will enforce this, so this test only needs
18038		// to configure the feature on the shim. Other application extensions
18039		// are sent implicitly.
18040		testCases = append(testCases, testCase{
18041			testType: clientTest,
18042			protocol: protocol,
18043			name:     prefix + "ECH-Client-NoNPN",
18044			config: Config{
18045				ServerECHConfigs: []ServerECHConfig{echConfig},
18046			},
18047			flags: []string{
18048				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18049				"-expect-ech-accept",
18050				// Enable NPN.
18051				"-select-next-proto", "foo",
18052			},
18053			expectations: connectionExpectations{echAccepted: true},
18054		})
18055
18056		// Test that the client iterates over configurations in the
18057		// ECHConfigList and selects the first with supported parameters.
18058		unsupportedKEM := generateServerECHConfig(&ECHConfig{
18059			KEM:       0x6666,
18060			PublicKey: []byte{1, 2, 3, 4},
18061		}).ECHConfig
18062		unsupportedCipherSuites := generateServerECHConfig(&ECHConfig{
18063			CipherSuites: []HPKECipherSuite{{0x1111, 0x2222}},
18064		}).ECHConfig
18065		unsupportedMandatoryExtension := generateServerECHConfig(&ECHConfig{
18066			UnsupportedMandatoryExtension: true,
18067		}).ECHConfig
18068		testCases = append(testCases, testCase{
18069			testType: clientTest,
18070			protocol: protocol,
18071			name:     prefix + "ECH-Client-SelectECHConfig",
18072			config: Config{
18073				ServerECHConfigs: []ServerECHConfig{echConfig},
18074			},
18075			flags: []string{
18076				"-ech-config-list", base64FlagValue(CreateECHConfigList(
18077					unsupportedVersion,
18078					unsupportedKEM.Raw,
18079					unsupportedCipherSuites.Raw,
18080					unsupportedMandatoryExtension.Raw,
18081					echConfig.ECHConfig.Raw,
18082					// |echConfig1| is also supported, but the client should
18083					// select the first one.
18084					echConfig1.ECHConfig.Raw,
18085				)),
18086				"-expect-ech-accept",
18087			},
18088			expectations: connectionExpectations{
18089				echAccepted: true,
18090			},
18091		})
18092
18093		// Test that the client skips sending ECH if all ECHConfigs are
18094		// unsupported.
18095		testCases = append(testCases, testCase{
18096			testType: clientTest,
18097			protocol: protocol,
18098			name:     prefix + "ECH-Client-NoSupportedConfigs",
18099			config: Config{
18100				Bugs: ProtocolBugs{
18101					ExpectNoClientECH: true,
18102				},
18103			},
18104			flags: []string{
18105				"-ech-config-list", base64FlagValue(CreateECHConfigList(
18106					unsupportedVersion,
18107					unsupportedKEM.Raw,
18108					unsupportedCipherSuites.Raw,
18109					unsupportedMandatoryExtension.Raw,
18110				)),
18111			},
18112		})
18113
18114		// If ECH GREASE is enabled, the client should send ECH GREASE when no
18115		// configured ECHConfig is suitable.
18116		testCases = append(testCases, testCase{
18117			testType: clientTest,
18118			protocol: protocol,
18119			name:     prefix + "ECH-Client-NoSupportedConfigs-GREASE",
18120			config: Config{
18121				Bugs: ProtocolBugs{
18122					ExpectClientECH: true,
18123				},
18124			},
18125			flags: []string{
18126				"-ech-config-list", base64FlagValue(CreateECHConfigList(
18127					unsupportedVersion,
18128					unsupportedKEM.Raw,
18129					unsupportedCipherSuites.Raw,
18130					unsupportedMandatoryExtension.Raw,
18131				)),
18132				"-enable-ech-grease",
18133			},
18134		})
18135
18136		// If both ECH GREASE and suitable ECHConfigs are available, the
18137		// client should send normal ECH.
18138		testCases = append(testCases, testCase{
18139			testType: clientTest,
18140			protocol: protocol,
18141			name:     prefix + "ECH-Client-GREASE",
18142			config: Config{
18143				ServerECHConfigs: []ServerECHConfig{echConfig},
18144			},
18145			flags: []string{
18146				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18147				"-expect-ech-accept",
18148			},
18149			resumeSession: true,
18150			expectations:  connectionExpectations{echAccepted: true},
18151		})
18152
18153		// Test that GREASE extensions correctly interact with ECH. Both the
18154		// inner and outer ClientHellos should include GREASE extensions.
18155		testCases = append(testCases, testCase{
18156			testType: clientTest,
18157			protocol: protocol,
18158			name:     prefix + "ECH-Client-GREASEExtensions",
18159			config: Config{
18160				ServerECHConfigs: []ServerECHConfig{echConfig},
18161				Bugs: ProtocolBugs{
18162					ExpectGREASE: true,
18163				},
18164			},
18165			flags: []string{
18166				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18167				"-expect-ech-accept",
18168				"-enable-grease",
18169			},
18170			resumeSession: true,
18171			expectations:  connectionExpectations{echAccepted: true},
18172		})
18173
18174		// Test that the client tolerates unsupported extensions if the
18175		// mandatory bit is not set.
18176		unsupportedExtension := generateServerECHConfig(&ECHConfig{UnsupportedExtension: true})
18177		testCases = append(testCases, testCase{
18178			testType: clientTest,
18179			protocol: protocol,
18180			name:     prefix + "ECH-Client-UnsupportedExtension",
18181			config: Config{
18182				ServerECHConfigs: []ServerECHConfig{unsupportedExtension},
18183			},
18184			flags: []string{
18185				"-ech-config-list", base64FlagValue(CreateECHConfigList(unsupportedExtension.ECHConfig.Raw)),
18186				"-expect-ech-accept",
18187			},
18188			expectations: connectionExpectations{echAccepted: true},
18189		})
18190
18191		// Syntax errors in the ECHConfigList should be rejected.
18192		testCases = append(testCases, testCase{
18193			testType: clientTest,
18194			protocol: protocol,
18195			name:     prefix + "ECH-Client-InvalidECHConfigList",
18196			flags: []string{
18197				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw[1:])),
18198			},
18199			shouldFail:    true,
18200			expectedError: ":INVALID_ECH_CONFIG_LIST:",
18201		})
18202
18203		// If the ClientHelloInner has no server_name extension, while the
18204		// ClientHelloOuter has one, the client must check for unsolicited
18205		// extensions based on the selected ClientHello.
18206		testCases = append(testCases, testCase{
18207			testType: clientTest,
18208			protocol: protocol,
18209			name:     prefix + "ECH-Client-UnsolicitedInnerServerNameAck",
18210			config: Config{
18211				ServerECHConfigs: []ServerECHConfig{echConfig},
18212				Bugs: ProtocolBugs{
18213					// ClientHelloOuter should have a server name.
18214					ExpectOuterServerName: "public.example",
18215					// The server will acknowledge the server_name extension.
18216					// This option runs whether or not the client requested the
18217					// extension.
18218					SendServerNameAck: true,
18219				},
18220			},
18221			flags: []string{
18222				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18223				// No -host-name flag.
18224				"-expect-ech-accept",
18225			},
18226			shouldFail:         true,
18227			expectedError:      ":UNEXPECTED_EXTENSION:",
18228			expectedLocalError: "remote error: unsupported extension",
18229			expectations:       connectionExpectations{echAccepted: true},
18230		})
18231
18232		// Most extensions are the same between ClientHelloInner and
18233		// ClientHelloOuter and can be compressed.
18234		testCases = append(testCases, testCase{
18235			testType: clientTest,
18236			protocol: protocol,
18237			name:     prefix + "ECH-Client-ExpectECHOuterExtensions",
18238			config: Config{
18239				ServerECHConfigs: []ServerECHConfig{echConfig},
18240				NextProtos:       []string{"proto"},
18241				Bugs: ProtocolBugs{
18242					ExpectECHOuterExtensions: []uint16{
18243						extensionALPN,
18244						extensionKeyShare,
18245						extensionPSKKeyExchangeModes,
18246						extensionSignatureAlgorithms,
18247						extensionSupportedCurves,
18248					},
18249				},
18250				Credential: &echSecretCertificate,
18251			},
18252			flags: []string{
18253				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18254				"-expect-ech-accept",
18255				"-advertise-alpn", "\x05proto",
18256				"-expect-alpn", "proto",
18257				"-host-name", "secret.example",
18258			},
18259			expectations: connectionExpectations{
18260				echAccepted: true,
18261				nextProto:   "proto",
18262			},
18263			skipQUICALPNConfig: true,
18264		})
18265
18266		// If the server name happens to match the public name, it still should
18267		// not be compressed. It is not publicly known that they match.
18268		testCases = append(testCases, testCase{
18269			testType: clientTest,
18270			protocol: protocol,
18271			name:     prefix + "ECH-Client-NeverCompressServerName",
18272			config: Config{
18273				ServerECHConfigs: []ServerECHConfig{echConfig},
18274				NextProtos:       []string{"proto"},
18275				Bugs: ProtocolBugs{
18276					ExpectECHUncompressedExtensions: []uint16{extensionServerName},
18277					ExpectServerName:                "public.example",
18278					ExpectOuterServerName:           "public.example",
18279				},
18280				Credential: &echPublicCertificate,
18281			},
18282			flags: []string{
18283				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18284				"-expect-ech-accept",
18285				"-host-name", "public.example",
18286			},
18287			expectations: connectionExpectations{echAccepted: true},
18288		})
18289
18290		// If the ClientHelloOuter disables TLS 1.3, e.g. in QUIC, the client
18291		// should also compress supported_versions.
18292		testCases = append(testCases, testCase{
18293			testType: clientTest,
18294			protocol: protocol,
18295			name:     prefix + "ECH-Client-CompressSupportedVersions",
18296			config: Config{
18297				ServerECHConfigs: []ServerECHConfig{echConfig},
18298				Bugs: ProtocolBugs{
18299					ExpectECHOuterExtensions: []uint16{
18300						extensionSupportedVersions,
18301					},
18302				},
18303				Credential: &echSecretCertificate,
18304			},
18305			flags: []string{
18306				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18307				"-host-name", "secret.example",
18308				"-expect-ech-accept",
18309				"-min-version", strconv.Itoa(int(VersionTLS13)),
18310			},
18311			expectations: connectionExpectations{echAccepted: true},
18312		})
18313
18314		// Test that the client can still offer server names that exceed the
18315		// maximum name length. It is only a padding hint.
18316		maxNameLen10 := generateServerECHConfig(&ECHConfig{MaxNameLen: 10})
18317		testCases = append(testCases, testCase{
18318			testType: clientTest,
18319			protocol: protocol,
18320			name:     prefix + "ECH-Client-NameTooLong",
18321			config: Config{
18322				ServerECHConfigs: []ServerECHConfig{maxNameLen10},
18323				Bugs: ProtocolBugs{
18324					ExpectServerName: "test0123456789.example",
18325				},
18326				Credential: &echLongNameCertificate,
18327			},
18328			flags: []string{
18329				"-ech-config-list", base64FlagValue(CreateECHConfigList(maxNameLen10.ECHConfig.Raw)),
18330				"-host-name", "test0123456789.example",
18331				"-expect-ech-accept",
18332			},
18333			expectations: connectionExpectations{echAccepted: true},
18334		})
18335
18336		// Test the client can recognize when ECH is rejected.
18337		testCases = append(testCases, testCase{
18338			testType: clientTest,
18339			protocol: protocol,
18340			name:     prefix + "ECH-Client-Reject",
18341			config: Config{
18342				ServerECHConfigs: []ServerECHConfig{echConfig2, echConfig3},
18343				Bugs: ProtocolBugs{
18344					ExpectServerName: "public.example",
18345				},
18346			},
18347			flags: []string{
18348				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18349				"-expect-ech-retry-configs", base64FlagValue(CreateECHConfigList(echConfig2.ECHConfig.Raw, echConfig3.ECHConfig.Raw)),
18350			},
18351			shouldFail:         true,
18352			expectedLocalError: "remote error: ECH required",
18353			expectedError:      ":ECH_REJECTED:",
18354		})
18355		testCases = append(testCases, testCase{
18356			testType: clientTest,
18357			protocol: protocol,
18358			name:     prefix + "ECH-Client-Reject-HelloRetryRequest",
18359			config: Config{
18360				ServerECHConfigs: []ServerECHConfig{echConfig2, echConfig3},
18361				CurvePreferences: []CurveID{CurveP384},
18362				Bugs: ProtocolBugs{
18363					ExpectServerName:      "public.example",
18364					ExpectMissingKeyShare: true, // Check we triggered HRR.
18365				},
18366			},
18367			flags: []string{
18368				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18369				"-expect-ech-retry-configs", base64FlagValue(CreateECHConfigList(echConfig2.ECHConfig.Raw, echConfig3.ECHConfig.Raw)),
18370				"-expect-hrr", // Check we triggered HRR.
18371			},
18372			shouldFail:         true,
18373			expectedLocalError: "remote error: ECH required",
18374			expectedError:      ":ECH_REJECTED:",
18375		})
18376		testCases = append(testCases, testCase{
18377			testType: clientTest,
18378			protocol: protocol,
18379			name:     prefix + "ECH-Client-Reject-NoRetryConfigs",
18380			config: Config{
18381				Bugs: ProtocolBugs{
18382					ExpectServerName: "public.example",
18383				},
18384			},
18385			flags: []string{
18386				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18387				"-expect-no-ech-retry-configs",
18388			},
18389			shouldFail:         true,
18390			expectedLocalError: "remote error: ECH required",
18391			expectedError:      ":ECH_REJECTED:",
18392		})
18393		if protocol != quic {
18394			testCases = append(testCases, testCase{
18395				testType: clientTest,
18396				protocol: protocol,
18397				name:     prefix + "ECH-Client-Reject-TLS12",
18398				config: Config{
18399					MaxVersion: VersionTLS12,
18400					Bugs: ProtocolBugs{
18401						ExpectServerName: "public.example",
18402					},
18403				},
18404				flags: []string{
18405					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18406					// TLS 1.2 cannot provide retry configs.
18407					"-expect-no-ech-retry-configs",
18408				},
18409				shouldFail:         true,
18410				expectedLocalError: "remote error: ECH required",
18411				expectedError:      ":ECH_REJECTED:",
18412			})
18413
18414			// Test that the client disables False Start when ECH is rejected.
18415			testCases = append(testCases, testCase{
18416				name: prefix + "ECH-Client-Reject-TLS12-NoFalseStart",
18417				config: Config{
18418					MaxVersion:   VersionTLS12,
18419					CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
18420					NextProtos:   []string{"foo"},
18421					Bugs: ProtocolBugs{
18422						// The options below cause the server to, immediately
18423						// after client Finished, send an alert and try to read
18424						// application data without sending server Finished.
18425						ExpectFalseStart:          true,
18426						AlertBeforeFalseStartTest: alertAccessDenied,
18427					},
18428				},
18429				flags: []string{
18430					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18431					"-false-start",
18432					"-advertise-alpn", "\x03foo",
18433					"-expect-alpn", "foo",
18434				},
18435				shimWritesFirst: true,
18436				shouldFail:      true,
18437				// Ensure the client does not send application data at the False
18438				// Start point. EOF comes from the client closing the connection
18439				// in response ot the alert.
18440				expectedLocalError: "tls: peer did not false start: EOF",
18441				// Ensures the client picks up the alert before reporting an
18442				// authenticated |SSL_R_ECH_REJECTED|.
18443				expectedError: ":TLSV1_ALERT_ACCESS_DENIED:",
18444			})
18445		}
18446
18447		// Test that unsupported retry configs in a valid ECHConfigList are
18448		// allowed. They will be skipped when configured in the retry.
18449		retryConfigs := CreateECHConfigList(
18450			unsupportedVersion,
18451			unsupportedKEM.Raw,
18452			unsupportedCipherSuites.Raw,
18453			unsupportedMandatoryExtension.Raw,
18454			echConfig2.ECHConfig.Raw)
18455		testCases = append(testCases, testCase{
18456			testType: clientTest,
18457			protocol: protocol,
18458			name:     prefix + "ECH-Client-Reject-UnsupportedRetryConfigs",
18459			config: Config{
18460				Bugs: ProtocolBugs{
18461					SendECHRetryConfigs: retryConfigs,
18462					ExpectServerName:    "public.example",
18463				},
18464			},
18465			flags: []string{
18466				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18467				"-expect-ech-retry-configs", base64FlagValue(retryConfigs),
18468			},
18469			shouldFail:         true,
18470			expectedLocalError: "remote error: ECH required",
18471			expectedError:      ":ECH_REJECTED:",
18472		})
18473
18474		// Test that the client rejects ClientHelloOuter handshakes that attempt
18475		// to resume the ClientHelloInner's ticket, at TLS 1.2 and TLS 1.3.
18476		testCases = append(testCases, testCase{
18477			testType: clientTest,
18478			protocol: protocol,
18479			name:     prefix + "ECH-Client-Reject-ResumeInnerSession-TLS13",
18480			config: Config{
18481				ServerECHConfigs: []ServerECHConfig{echConfig},
18482				Bugs: ProtocolBugs{
18483					ExpectServerName: "secret.example",
18484				},
18485				Credential: &echSecretCertificate,
18486			},
18487			resumeConfig: &Config{
18488				MaxVersion:       VersionTLS13,
18489				ServerECHConfigs: []ServerECHConfig{echConfig},
18490				Bugs: ProtocolBugs{
18491					ExpectServerName:                    "public.example",
18492					UseInnerSessionWithClientHelloOuter: true,
18493				},
18494				Credential: &echPublicCertificate,
18495			},
18496			resumeSession: true,
18497			flags: []string{
18498				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18499				"-host-name", "secret.example",
18500				"-on-initial-expect-ech-accept",
18501			},
18502			shouldFail:         true,
18503			expectedError:      ":UNEXPECTED_EXTENSION:",
18504			expectations:       connectionExpectations{echAccepted: true},
18505			resumeExpectations: &connectionExpectations{echAccepted: false},
18506		})
18507		if protocol != quic {
18508			testCases = append(testCases, testCase{
18509				testType: clientTest,
18510				protocol: protocol,
18511				name:     prefix + "ECH-Client-Reject-ResumeInnerSession-TLS12",
18512				config: Config{
18513					ServerECHConfigs: []ServerECHConfig{echConfig},
18514					Bugs: ProtocolBugs{
18515						ExpectServerName: "secret.example",
18516					},
18517					Credential: &echSecretCertificate,
18518				},
18519				resumeConfig: &Config{
18520					MinVersion:       VersionTLS12,
18521					MaxVersion:       VersionTLS12,
18522					ServerECHConfigs: []ServerECHConfig{echConfig},
18523					Bugs: ProtocolBugs{
18524						ExpectServerName:                    "public.example",
18525						UseInnerSessionWithClientHelloOuter: true,
18526						// The client only ever offers TLS 1.3 sessions in
18527						// ClientHelloInner. AcceptAnySession allows them to be
18528						// resumed at TLS 1.2.
18529						AcceptAnySession: true,
18530					},
18531					Credential: &echPublicCertificate,
18532				},
18533				resumeSession: true,
18534				flags: []string{
18535					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18536					"-host-name", "secret.example",
18537					"-on-initial-expect-ech-accept",
18538				},
18539				// From the client's perspective, the server echoed a session ID to
18540				// signal resumption, but the selected ClientHello had nothing to
18541				// resume.
18542				shouldFail:         true,
18543				expectedError:      ":SERVER_ECHOED_INVALID_SESSION_ID:",
18544				expectedLocalError: "remote error: illegal parameter",
18545				expectations:       connectionExpectations{echAccepted: true},
18546				resumeExpectations: &connectionExpectations{echAccepted: false},
18547			})
18548		}
18549
18550		// Test that the client can process ECH rejects after an early data reject.
18551		testCases = append(testCases, testCase{
18552			testType: clientTest,
18553			protocol: protocol,
18554			name:     prefix + "ECH-Client-Reject-EarlyDataRejected",
18555			config: Config{
18556				ServerECHConfigs: []ServerECHConfig{echConfig},
18557				Bugs: ProtocolBugs{
18558					ExpectServerName: "secret.example",
18559				},
18560				Credential: &echSecretCertificate,
18561			},
18562			resumeConfig: &Config{
18563				ServerECHConfigs: []ServerECHConfig{echConfig2},
18564				Bugs: ProtocolBugs{
18565					ExpectServerName: "public.example",
18566				},
18567				Credential: &echPublicCertificate,
18568			},
18569			flags: []string{
18570				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18571				"-host-name", "secret.example",
18572				// Although the resumption connection does not accept ECH, the
18573				// API will report ECH was accepted at the 0-RTT point.
18574				"-expect-ech-accept",
18575				// -on-retry refers to the retried handshake after 0-RTT reject,
18576				// while ech-retry-configs refers to the ECHConfigs to use in
18577				// the next connection attempt.
18578				"-on-retry-expect-ech-retry-configs", base64FlagValue(CreateECHConfigList(echConfig2.ECHConfig.Raw)),
18579			},
18580			resumeSession:           true,
18581			expectResumeRejected:    true,
18582			earlyData:               true,
18583			expectEarlyDataRejected: true,
18584			expectations:            connectionExpectations{echAccepted: true},
18585			resumeExpectations:      &connectionExpectations{echAccepted: false},
18586			shouldFail:              true,
18587			expectedLocalError:      "remote error: ECH required",
18588			expectedError:           ":ECH_REJECTED:",
18589		})
18590		if protocol != quic {
18591			testCases = append(testCases, testCase{
18592				testType: clientTest,
18593				protocol: protocol,
18594				name:     prefix + "ECH-Client-Reject-EarlyDataRejected-TLS12",
18595				config: Config{
18596					ServerECHConfigs: []ServerECHConfig{echConfig},
18597					Bugs: ProtocolBugs{
18598						ExpectServerName: "secret.example",
18599					},
18600					Credential: &echSecretCertificate,
18601				},
18602				resumeConfig: &Config{
18603					MaxVersion: VersionTLS12,
18604					Bugs: ProtocolBugs{
18605						ExpectServerName: "public.example",
18606					},
18607					Credential: &echPublicCertificate,
18608				},
18609				flags: []string{
18610					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18611					"-host-name", "secret.example",
18612					// Although the resumption connection does not accept ECH, the
18613					// API will report ECH was accepted at the 0-RTT point.
18614					"-expect-ech-accept",
18615				},
18616				resumeSession:           true,
18617				expectResumeRejected:    true,
18618				earlyData:               true,
18619				expectEarlyDataRejected: true,
18620				expectations:            connectionExpectations{echAccepted: true},
18621				resumeExpectations:      &connectionExpectations{echAccepted: false},
18622				// ClientHellos with early data cannot negotiate TLS 1.2, with
18623				// or without ECH. The shim should first report
18624				// |SSL_R_WRONG_VERSION_ON_EARLY_DATA|. The caller will then
18625				// repair the first error by retrying without early data. That
18626				// will look like ECH-Client-Reject-TLS12 and select TLS 1.2
18627				// and ClientHelloOuter. The caller will then trigger a third
18628				// attempt, which will succeed.
18629				shouldFail:    true,
18630				expectedError: ":WRONG_VERSION_ON_EARLY_DATA:",
18631			})
18632		}
18633
18634		// Test that the client ignores ECHConfigs with invalid public names.
18635		invalidPublicName := generateServerECHConfig(&ECHConfig{PublicName: "dns_names_have_no_underscores.example"})
18636		testCases = append(testCases, testCase{
18637			testType: clientTest,
18638			protocol: protocol,
18639			name:     prefix + "ECH-Client-SkipInvalidPublicName",
18640			config: Config{
18641				Bugs: ProtocolBugs{
18642					// No ECHConfigs are supported, so the client should fall
18643					// back to cleartext.
18644					ExpectNoClientECH: true,
18645					ExpectServerName:  "secret.example",
18646				},
18647				Credential: &echSecretCertificate,
18648			},
18649			flags: []string{
18650				"-ech-config-list", base64FlagValue(CreateECHConfigList(invalidPublicName.ECHConfig.Raw)),
18651				"-host-name", "secret.example",
18652			},
18653		})
18654		testCases = append(testCases, testCase{
18655			testType: clientTest,
18656			protocol: protocol,
18657			name:     prefix + "ECH-Client-SkipInvalidPublicName-2",
18658			config: Config{
18659				// The client should skip |invalidPublicName| and use |echConfig|.
18660				ServerECHConfigs: []ServerECHConfig{echConfig},
18661				Bugs: ProtocolBugs{
18662					ExpectOuterServerName: "public.example",
18663					ExpectServerName:      "secret.example",
18664				},
18665				Credential: &echSecretCertificate,
18666			},
18667			flags: []string{
18668				"-ech-config-list", base64FlagValue(CreateECHConfigList(invalidPublicName.ECHConfig.Raw, echConfig.ECHConfig.Raw)),
18669				"-host-name", "secret.example",
18670				"-expect-ech-accept",
18671			},
18672			expectations: connectionExpectations{echAccepted: true},
18673		})
18674
18675		// Test both sync and async mode, to test both with and without the
18676		// client certificate callback.
18677		for _, async := range []bool{false, true} {
18678			var flags []string
18679			var suffix string
18680			if async {
18681				flags = []string{"-async"}
18682				suffix = "-Async"
18683			}
18684
18685			// Test that ECH and client certificates can be used together.
18686			testCases = append(testCases, testCase{
18687				testType: clientTest,
18688				protocol: protocol,
18689				name:     prefix + "ECH-Client-ClientCertificate" + suffix,
18690				config: Config{
18691					ServerECHConfigs: []ServerECHConfig{echConfig},
18692					ClientAuth:       RequireAnyClientCert,
18693				},
18694				shimCertificate: &rsaCertificate,
18695				flags: append([]string{
18696					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18697					"-expect-ech-accept",
18698				}, flags...),
18699				expectations: connectionExpectations{echAccepted: true},
18700			})
18701
18702			// Test that, when ECH is rejected, the client does not send a client
18703			// certificate.
18704			testCases = append(testCases, testCase{
18705				testType: clientTest,
18706				protocol: protocol,
18707				name:     prefix + "ECH-Client-Reject-NoClientCertificate-TLS13" + suffix,
18708				config: Config{
18709					MinVersion: VersionTLS13,
18710					MaxVersion: VersionTLS13,
18711					ClientAuth: RequireAnyClientCert,
18712				},
18713				shimCertificate: &rsaCertificate,
18714				flags: append([]string{
18715					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18716				}, flags...),
18717				shouldFail:         true,
18718				expectedLocalError: "tls: client didn't provide a certificate",
18719			})
18720			if protocol != quic {
18721				testCases = append(testCases, testCase{
18722					testType: clientTest,
18723					protocol: protocol,
18724					name:     prefix + "ECH-Client-Reject-NoClientCertificate-TLS12" + suffix,
18725					config: Config{
18726						MinVersion: VersionTLS12,
18727						MaxVersion: VersionTLS12,
18728						ClientAuth: RequireAnyClientCert,
18729					},
18730					shimCertificate: &rsaCertificate,
18731					flags: append([]string{
18732						"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18733					}, flags...),
18734					shouldFail:         true,
18735					expectedLocalError: "tls: client didn't provide a certificate",
18736				})
18737			}
18738		}
18739
18740		// Test that ECH and Channel ID can be used together.
18741		testCases = append(testCases, testCase{
18742			testType: clientTest,
18743			protocol: protocol,
18744			name:     prefix + "ECH-Client-ChannelID",
18745			config: Config{
18746				ServerECHConfigs: []ServerECHConfig{echConfig},
18747				RequestChannelID: true,
18748			},
18749			flags: []string{
18750				"-send-channel-id", channelIDKeyPath,
18751				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18752				"-expect-ech-accept",
18753			},
18754			resumeSession: true,
18755			expectations: connectionExpectations{
18756				channelID:   true,
18757				echAccepted: true,
18758			},
18759		})
18760
18761		// Handshakes where ECH is rejected do not offer or accept Channel ID.
18762		testCases = append(testCases, testCase{
18763			testType: clientTest,
18764			protocol: protocol,
18765			name:     prefix + "ECH-Client-Reject-NoChannelID-TLS13",
18766			config: Config{
18767				MinVersion: VersionTLS13,
18768				MaxVersion: VersionTLS13,
18769				Bugs: ProtocolBugs{
18770					AlwaysNegotiateChannelID: true,
18771				},
18772			},
18773			flags: []string{
18774				"-send-channel-id", channelIDKeyPath,
18775				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18776			},
18777			shouldFail:         true,
18778			expectedLocalError: "remote error: unsupported extension",
18779			expectedError:      ":UNEXPECTED_EXTENSION:",
18780		})
18781		if protocol != quic {
18782			testCases = append(testCases, testCase{
18783				testType: clientTest,
18784				protocol: protocol,
18785				name:     prefix + "ECH-Client-Reject-NoChannelID-TLS12",
18786				config: Config{
18787					MinVersion: VersionTLS12,
18788					MaxVersion: VersionTLS12,
18789					Bugs: ProtocolBugs{
18790						AlwaysNegotiateChannelID: true,
18791					},
18792				},
18793				flags: []string{
18794					"-send-channel-id", channelIDKeyPath,
18795					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18796				},
18797				shouldFail:         true,
18798				expectedLocalError: "remote error: unsupported extension",
18799				expectedError:      ":UNEXPECTED_EXTENSION:",
18800			})
18801		}
18802
18803		// Test that ECH correctly overrides the host name for certificate
18804		// verification.
18805		testCases = append(testCases, testCase{
18806			testType: clientTest,
18807			protocol: protocol,
18808			name:     prefix + "ECH-Client-NotOffered-NoOverrideName",
18809			flags: []string{
18810				"-verify-peer",
18811				"-use-custom-verify-callback",
18812				// When not offering ECH, verify the usual name in both full
18813				// and resumption handshakes.
18814				"-reverify-on-resume",
18815				"-expect-no-ech-name-override",
18816			},
18817			resumeSession: true,
18818		})
18819		testCases = append(testCases, testCase{
18820			testType: clientTest,
18821			protocol: protocol,
18822			name:     prefix + "ECH-Client-GREASE-NoOverrideName",
18823			flags: []string{
18824				"-verify-peer",
18825				"-use-custom-verify-callback",
18826				"-enable-ech-grease",
18827				// When offering ECH GREASE, verify the usual name in both full
18828				// and resumption handshakes.
18829				"-reverify-on-resume",
18830				"-expect-no-ech-name-override",
18831			},
18832			resumeSession: true,
18833		})
18834		if protocol != quic {
18835			testCases = append(testCases, testCase{
18836				testType: clientTest,
18837				protocol: protocol,
18838				name:     prefix + "ECH-Client-Rejected-OverrideName-TLS12",
18839				config: Config{
18840					MinVersion: VersionTLS12,
18841					MaxVersion: VersionTLS12,
18842				},
18843				flags: []string{
18844					"-verify-peer",
18845					"-use-custom-verify-callback",
18846					"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18847					// When ECH is rejected, verify the public name. This can
18848					// only happen in full handshakes.
18849					"-expect-ech-name-override", "public.example",
18850				},
18851				shouldFail:         true,
18852				expectedError:      ":ECH_REJECTED:",
18853				expectedLocalError: "remote error: ECH required",
18854			})
18855		}
18856		testCases = append(testCases, testCase{
18857			testType: clientTest,
18858			protocol: protocol,
18859			name:     prefix + "ECH-Client-Reject-OverrideName-TLS13",
18860			config: Config{
18861				MinVersion: VersionTLS13,
18862				MaxVersion: VersionTLS13,
18863			},
18864			flags: []string{
18865				"-verify-peer",
18866				"-use-custom-verify-callback",
18867				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18868				// When ECH is rejected, verify the public name. This can
18869				// only happen in full handshakes.
18870				"-expect-ech-name-override", "public.example",
18871			},
18872			shouldFail:         true,
18873			expectedError:      ":ECH_REJECTED:",
18874			expectedLocalError: "remote error: ECH required",
18875		})
18876		testCases = append(testCases, testCase{
18877			testType: clientTest,
18878			protocol: protocol,
18879			name:     prefix + "ECH-Client-Accept-NoOverrideName",
18880			config: Config{
18881				ServerECHConfigs: []ServerECHConfig{echConfig},
18882			},
18883			flags: []string{
18884				"-verify-peer",
18885				"-use-custom-verify-callback",
18886				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18887				"-expect-ech-accept",
18888				// When ECH is accepted, verify the usual name in both full and
18889				// resumption handshakes.
18890				"-reverify-on-resume",
18891				"-expect-no-ech-name-override",
18892			},
18893			resumeSession: true,
18894			expectations:  connectionExpectations{echAccepted: true},
18895		})
18896		testCases = append(testCases, testCase{
18897			testType: clientTest,
18898			protocol: protocol,
18899			name:     prefix + "ECH-Client-Reject-EarlyDataRejected-OverrideNameOnRetry",
18900			config: Config{
18901				ServerECHConfigs: []ServerECHConfig{echConfig},
18902			},
18903			resumeConfig: &Config{},
18904			flags: []string{
18905				"-verify-peer",
18906				"-use-custom-verify-callback",
18907				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18908				// Although the resumption connection does not accept ECH, the
18909				// API will report ECH was accepted at the 0-RTT point.
18910				"-expect-ech-accept",
18911				// The resumption connection verifies certificates twice. First,
18912				// if reverification is enabled, we verify the 0-RTT certificate
18913				// as if ECH as accepted. There should be no name override.
18914				// Next, on the post-0-RTT-rejection retry, we verify the new
18915				// server certificate. This picks up the ECH reject, so it
18916				// should use public.example.
18917				"-reverify-on-resume",
18918				"-on-resume-expect-no-ech-name-override",
18919				"-on-retry-expect-ech-name-override", "public.example",
18920			},
18921			resumeSession:           true,
18922			expectResumeRejected:    true,
18923			earlyData:               true,
18924			expectEarlyDataRejected: true,
18925			expectations:            connectionExpectations{echAccepted: true},
18926			resumeExpectations:      &connectionExpectations{echAccepted: false},
18927			shouldFail:              true,
18928			expectedError:           ":ECH_REJECTED:",
18929			expectedLocalError:      "remote error: ECH required",
18930		})
18931
18932		// Test that the client checks both HelloRetryRequest and ServerHello
18933		// for a confirmation signal.
18934		testCases = append(testCases, testCase{
18935			testType: clientTest,
18936			protocol: protocol,
18937			name:     prefix + "ECH-Client-HelloRetryRequest-MissingServerHelloConfirmation",
18938			config: Config{
18939				MinVersion:       VersionTLS13,
18940				MaxVersion:       VersionTLS13,
18941				CurvePreferences: []CurveID{CurveP384},
18942				ServerECHConfigs: []ServerECHConfig{echConfig},
18943				Bugs: ProtocolBugs{
18944					ExpectMissingKeyShare:          true, // Check we triggered HRR.
18945					OmitServerHelloECHConfirmation: true,
18946				},
18947			},
18948			resumeSession: true,
18949			flags: []string{
18950				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18951				"-expect-hrr", // Check we triggered HRR.
18952			},
18953			shouldFail:    true,
18954			expectedError: ":INCONSISTENT_ECH_NEGOTIATION:",
18955		})
18956
18957		// Test the message callback is correctly reported, with and without
18958		// HelloRetryRequest.
18959		clientAndServerHello := "write clienthelloinner\nwrite hs 1\nread hs 2\n"
18960		// EncryptedExtensions onwards.
18961		finishHandshake := `read hs 8
18962read hs 11
18963read hs 15
18964read hs 20
18965write hs 20
18966read hs 4
18967read hs 4
18968`
18969		testCases = append(testCases, testCase{
18970			testType: clientTest,
18971			protocol: protocol,
18972			name:     prefix + "ECH-Client-MessageCallback",
18973			config: Config{
18974				MinVersion:       VersionTLS13,
18975				MaxVersion:       VersionTLS13,
18976				ServerECHConfigs: []ServerECHConfig{echConfig},
18977				Bugs: ProtocolBugs{
18978					NoCloseNotify: true, // Align QUIC and TCP traces.
18979				},
18980			},
18981			flags: []string{
18982				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
18983				"-expect-ech-accept",
18984				"-expect-msg-callback", clientAndServerHello + "write ccs\n" + finishHandshake,
18985			},
18986			expectations: connectionExpectations{echAccepted: true},
18987		})
18988		testCases = append(testCases, testCase{
18989			testType: clientTest,
18990			protocol: protocol,
18991			name:     prefix + "ECH-Client-MessageCallback-HelloRetryRequest",
18992			config: Config{
18993				MinVersion:       VersionTLS13,
18994				MaxVersion:       VersionTLS13,
18995				CurvePreferences: []CurveID{CurveP384},
18996				ServerECHConfigs: []ServerECHConfig{echConfig},
18997				Bugs: ProtocolBugs{
18998					ExpectMissingKeyShare: true, // Check we triggered HRR.
18999					NoCloseNotify:         true, // Align QUIC and TCP traces.
19000				},
19001			},
19002			flags: []string{
19003				"-ech-config-list", base64FlagValue(CreateECHConfigList(echConfig.ECHConfig.Raw)),
19004				"-expect-ech-accept",
19005				"-expect-hrr", // Check we triggered HRR.
19006				"-expect-msg-callback", clientAndServerHello + "write ccs\n" + clientAndServerHello + finishHandshake,
19007			},
19008			expectations: connectionExpectations{echAccepted: true},
19009		})
19010	}
19011}
19012
19013func addHintMismatchTests() {
19014	// Each of these tests skips split handshakes because split handshakes does
19015	// not handle a mismatch between shim and handshaker. Handshake hints,
19016	// however, are designed to tolerate the mismatch.
19017	//
19018	// Note also these tests do not specify -handshake-hints directly. Instead,
19019	// we define normal tests, that run even without a handshaker, and rely on
19020	// convertToSplitHandshakeTests to generate a handshaker hints variant. This
19021	// avoids repeating the -is-handshaker-supported and -handshaker-path logic.
19022	// (While not useful, the tests will still pass without a handshaker.)
19023	for _, protocol := range []protocol{tls, quic} {
19024		// If the signing payload is different, the handshake still completes
19025		// successfully. Different ALPN preferences will trigger a mismatch.
19026		testCases = append(testCases, testCase{
19027			name:               protocol.String() + "-HintMismatch-SignatureInput",
19028			testType:           serverTest,
19029			protocol:           protocol,
19030			skipSplitHandshake: true,
19031			config: Config{
19032				MinVersion: VersionTLS13,
19033				MaxVersion: VersionTLS13,
19034				NextProtos: []string{"foo", "bar"},
19035			},
19036			flags: []string{
19037				"-allow-hint-mismatch",
19038				"-on-shim-select-alpn", "foo",
19039				"-on-handshaker-select-alpn", "bar",
19040			},
19041			expectations: connectionExpectations{
19042				nextProto:     "foo",
19043				nextProtoType: alpn,
19044			},
19045		})
19046
19047		// The shim and handshaker may have different curve preferences.
19048		testCases = append(testCases, testCase{
19049			name:               protocol.String() + "-HintMismatch-KeyShare",
19050			testType:           serverTest,
19051			protocol:           protocol,
19052			skipSplitHandshake: true,
19053			config: Config{
19054				MinVersion: VersionTLS13,
19055				MaxVersion: VersionTLS13,
19056				// Send both curves in the key share list, to avoid getting
19057				// mixed up with HelloRetryRequest.
19058				DefaultCurves: []CurveID{CurveX25519, CurveP256},
19059			},
19060			flags: []string{
19061				"-allow-hint-mismatch",
19062				"-on-shim-curves", strconv.Itoa(int(CurveX25519)),
19063				"-on-handshaker-curves", strconv.Itoa(int(CurveP256)),
19064			},
19065			expectations: connectionExpectations{
19066				curveID: CurveX25519,
19067			},
19068		})
19069		if protocol != quic {
19070			testCases = append(testCases, testCase{
19071				name:               protocol.String() + "-HintMismatch-ECDHE-Group",
19072				testType:           serverTest,
19073				protocol:           protocol,
19074				skipSplitHandshake: true,
19075				config: Config{
19076					MinVersion:    VersionTLS12,
19077					MaxVersion:    VersionTLS12,
19078					DefaultCurves: []CurveID{CurveX25519, CurveP256},
19079				},
19080				flags: []string{
19081					"-allow-hint-mismatch",
19082					"-on-shim-curves", strconv.Itoa(int(CurveX25519)),
19083					"-on-handshaker-curves", strconv.Itoa(int(CurveP256)),
19084				},
19085				expectations: connectionExpectations{
19086					curveID: CurveX25519,
19087				},
19088			})
19089		}
19090
19091		// If the handshaker does HelloRetryRequest, it will omit most hints.
19092		// The shim should still work.
19093		testCases = append(testCases, testCase{
19094			name:               protocol.String() + "-HintMismatch-HandshakerHelloRetryRequest",
19095			testType:           serverTest,
19096			protocol:           protocol,
19097			skipSplitHandshake: true,
19098			config: Config{
19099				MinVersion:    VersionTLS13,
19100				MaxVersion:    VersionTLS13,
19101				DefaultCurves: []CurveID{CurveX25519},
19102			},
19103			flags: []string{
19104				"-allow-hint-mismatch",
19105				"-on-shim-curves", strconv.Itoa(int(CurveX25519)),
19106				"-on-handshaker-curves", strconv.Itoa(int(CurveP256)),
19107			},
19108			expectations: connectionExpectations{
19109				curveID: CurveX25519,
19110			},
19111		})
19112
19113		// If the shim does HelloRetryRequest, the hints from the handshaker
19114		// will be ignored. This is not reported as a mismatch because hints
19115		// would not have helped the shim anyway.
19116		testCases = append(testCases, testCase{
19117			name:               protocol.String() + "-HintMismatch-ShimHelloRetryRequest",
19118			testType:           serverTest,
19119			protocol:           protocol,
19120			skipSplitHandshake: true,
19121			config: Config{
19122				MinVersion:    VersionTLS13,
19123				MaxVersion:    VersionTLS13,
19124				DefaultCurves: []CurveID{CurveX25519},
19125			},
19126			flags: []string{
19127				"-on-shim-curves", strconv.Itoa(int(CurveP256)),
19128				"-on-handshaker-curves", strconv.Itoa(int(CurveX25519)),
19129			},
19130			expectations: connectionExpectations{
19131				curveID: CurveP256,
19132			},
19133		})
19134
19135		// The shim and handshaker may have different signature algorithm
19136		// preferences.
19137		testCases = append(testCases, testCase{
19138			name:               protocol.String() + "-HintMismatch-SignatureAlgorithm-TLS13",
19139			testType:           serverTest,
19140			protocol:           protocol,
19141			skipSplitHandshake: true,
19142			config: Config{
19143				MinVersion: VersionTLS13,
19144				MaxVersion: VersionTLS13,
19145				VerifySignatureAlgorithms: []signatureAlgorithm{
19146					signatureRSAPSSWithSHA256,
19147					signatureRSAPSSWithSHA384,
19148				},
19149			},
19150			shimCertificate:       rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
19151			handshakerCertificate: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA384),
19152			flags:                 []string{"-allow-hint-mismatch"},
19153			expectations: connectionExpectations{
19154				peerSignatureAlgorithm: signatureRSAPSSWithSHA256,
19155			},
19156		})
19157		if protocol != quic {
19158			testCases = append(testCases, testCase{
19159				name:               protocol.String() + "-HintMismatch-SignatureAlgorithm-TLS12",
19160				testType:           serverTest,
19161				protocol:           protocol,
19162				skipSplitHandshake: true,
19163				config: Config{
19164					MinVersion: VersionTLS12,
19165					MaxVersion: VersionTLS12,
19166					VerifySignatureAlgorithms: []signatureAlgorithm{
19167						signatureRSAPSSWithSHA256,
19168						signatureRSAPSSWithSHA384,
19169					},
19170				},
19171				shimCertificate:       rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
19172				handshakerCertificate: rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA384),
19173				flags:                 []string{"-allow-hint-mismatch"},
19174				expectations: connectionExpectations{
19175					peerSignatureAlgorithm: signatureRSAPSSWithSHA256,
19176				},
19177			})
19178		}
19179
19180		// The shim and handshaker may use different certificates. In TLS 1.3,
19181		// the signature input includes the certificate, so we do not need to
19182		// explicitly check for a public key match. In TLS 1.2, it does not.
19183		ecdsaP256Certificate2 := generateSingleCertChain(nil, &channelIDKey)
19184		testCases = append(testCases, testCase{
19185			name:               protocol.String() + "-HintMismatch-Certificate-TLS13",
19186			testType:           serverTest,
19187			protocol:           protocol,
19188			skipSplitHandshake: true,
19189			config: Config{
19190				MinVersion: VersionTLS13,
19191				MaxVersion: VersionTLS13,
19192			},
19193			shimCertificate:       &ecdsaP256Certificate,
19194			handshakerCertificate: &ecdsaP256Certificate2,
19195			flags:                 []string{"-allow-hint-mismatch"},
19196			expectations: connectionExpectations{
19197				peerCertificate: &ecdsaP256Certificate,
19198			},
19199		})
19200		if protocol != quic {
19201			testCases = append(testCases, testCase{
19202				name:               protocol.String() + "-HintMismatch-Certificate-TLS12",
19203				testType:           serverTest,
19204				protocol:           protocol,
19205				skipSplitHandshake: true,
19206				config: Config{
19207					MinVersion: VersionTLS12,
19208					MaxVersion: VersionTLS12,
19209				},
19210				shimCertificate:       &ecdsaP256Certificate,
19211				handshakerCertificate: &ecdsaP256Certificate2,
19212				flags:                 []string{"-allow-hint-mismatch"},
19213				expectations: connectionExpectations{
19214					peerCertificate: &ecdsaP256Certificate,
19215				},
19216			})
19217		}
19218
19219		// The shim and handshaker may disagree on whether resumption is allowed.
19220		// We run the first connection with tickets enabled, so the client is
19221		// issued a ticket, then disable tickets on the second connection.
19222		testCases = append(testCases, testCase{
19223			name:               protocol.String() + "-HintMismatch-NoTickets1-TLS13",
19224			testType:           serverTest,
19225			protocol:           protocol,
19226			skipSplitHandshake: true,
19227			config: Config{
19228				MinVersion: VersionTLS13,
19229				MaxVersion: VersionTLS13,
19230			},
19231			flags: []string{
19232				"-on-resume-allow-hint-mismatch",
19233				"-on-shim-on-resume-no-ticket",
19234			},
19235			resumeSession:        true,
19236			expectResumeRejected: true,
19237		})
19238		testCases = append(testCases, testCase{
19239			name:               protocol.String() + "-HintMismatch-NoTickets2-TLS13",
19240			testType:           serverTest,
19241			protocol:           protocol,
19242			skipSplitHandshake: true,
19243			config: Config{
19244				MinVersion: VersionTLS13,
19245				MaxVersion: VersionTLS13,
19246			},
19247			flags: []string{
19248				"-on-resume-allow-hint-mismatch",
19249				"-on-handshaker-on-resume-no-ticket",
19250			},
19251			resumeSession: true,
19252		})
19253		if protocol != quic {
19254			testCases = append(testCases, testCase{
19255				name:               protocol.String() + "-HintMismatch-NoTickets1-TLS12",
19256				testType:           serverTest,
19257				protocol:           protocol,
19258				skipSplitHandshake: true,
19259				config: Config{
19260					MinVersion: VersionTLS12,
19261					MaxVersion: VersionTLS12,
19262				},
19263				flags: []string{
19264					"-on-resume-allow-hint-mismatch",
19265					"-on-shim-on-resume-no-ticket",
19266				},
19267				resumeSession:        true,
19268				expectResumeRejected: true,
19269			})
19270			testCases = append(testCases, testCase{
19271				name:               protocol.String() + "-HintMismatch-NoTickets2-TLS12",
19272				testType:           serverTest,
19273				protocol:           protocol,
19274				skipSplitHandshake: true,
19275				config: Config{
19276					MinVersion: VersionTLS12,
19277					MaxVersion: VersionTLS12,
19278				},
19279				flags: []string{
19280					"-on-resume-allow-hint-mismatch",
19281					"-on-handshaker-on-resume-no-ticket",
19282				},
19283				resumeSession: true,
19284			})
19285		}
19286
19287		// The shim and handshaker may disagree on whether to request a client
19288		// certificate.
19289		testCases = append(testCases, testCase{
19290			name:               protocol.String() + "-HintMismatch-CertificateRequest",
19291			testType:           serverTest,
19292			protocol:           protocol,
19293			skipSplitHandshake: true,
19294			config: Config{
19295				MinVersion: VersionTLS13,
19296				MaxVersion: VersionTLS13,
19297				Credential: &rsaCertificate,
19298			},
19299			flags: []string{
19300				"-allow-hint-mismatch",
19301				"-on-shim-require-any-client-certificate",
19302			},
19303		})
19304
19305		// The shim and handshaker may negotiate different versions altogether.
19306		if protocol != quic {
19307			testCases = append(testCases, testCase{
19308				name:               protocol.String() + "-HintMismatch-Version1",
19309				testType:           serverTest,
19310				protocol:           protocol,
19311				skipSplitHandshake: true,
19312				config: Config{
19313					MinVersion: VersionTLS12,
19314					MaxVersion: VersionTLS13,
19315				},
19316				flags: []string{
19317					"-allow-hint-mismatch",
19318					"-on-shim-max-version", strconv.Itoa(VersionTLS12),
19319					"-on-handshaker-max-version", strconv.Itoa(VersionTLS13),
19320				},
19321				expectations: connectionExpectations{
19322					version: VersionTLS12,
19323				},
19324			})
19325			testCases = append(testCases, testCase{
19326				name:               protocol.String() + "-HintMismatch-Version2",
19327				testType:           serverTest,
19328				protocol:           protocol,
19329				skipSplitHandshake: true,
19330				config: Config{
19331					MinVersion: VersionTLS12,
19332					MaxVersion: VersionTLS13,
19333				},
19334				flags: []string{
19335					"-allow-hint-mismatch",
19336					"-on-shim-max-version", strconv.Itoa(VersionTLS13),
19337					"-on-handshaker-max-version", strconv.Itoa(VersionTLS12),
19338				},
19339				expectations: connectionExpectations{
19340					version: VersionTLS13,
19341				},
19342			})
19343		}
19344
19345		// The shim and handshaker may disagree on the certificate compression
19346		// algorithm, whether to enable certificate compression, or certificate
19347		// compression inputs.
19348		testCases = append(testCases, testCase{
19349			name:               protocol.String() + "-HintMismatch-CertificateCompression-ShimOnly",
19350			testType:           serverTest,
19351			protocol:           protocol,
19352			skipSplitHandshake: true,
19353			config: Config{
19354				MinVersion: VersionTLS13,
19355				MaxVersion: VersionTLS13,
19356				CertCompressionAlgs: map[uint16]CertCompressionAlg{
19357					shrinkingCompressionAlgID: shrinkingCompression,
19358				},
19359				Bugs: ProtocolBugs{
19360					ExpectedCompressedCert: shrinkingCompressionAlgID,
19361				},
19362			},
19363			flags: []string{
19364				"-allow-hint-mismatch",
19365				"-on-shim-install-cert-compression-algs",
19366			},
19367		})
19368		testCases = append(testCases, testCase{
19369			name:               protocol.String() + "-HintMismatch-CertificateCompression-HandshakerOnly",
19370			testType:           serverTest,
19371			protocol:           protocol,
19372			skipSplitHandshake: true,
19373			config: Config{
19374				MinVersion: VersionTLS13,
19375				MaxVersion: VersionTLS13,
19376				CertCompressionAlgs: map[uint16]CertCompressionAlg{
19377					shrinkingCompressionAlgID: shrinkingCompression,
19378				},
19379				Bugs: ProtocolBugs{
19380					ExpectUncompressedCert: true,
19381				},
19382			},
19383			flags: []string{
19384				"-allow-hint-mismatch",
19385				"-on-handshaker-install-cert-compression-algs",
19386			},
19387		})
19388		testCases = append(testCases, testCase{
19389			testType:           serverTest,
19390			name:               protocol.String() + "-HintMismatch-CertificateCompression-AlgorithmMismatch",
19391			protocol:           protocol,
19392			skipSplitHandshake: true,
19393			config: Config{
19394				MinVersion: VersionTLS13,
19395				MaxVersion: VersionTLS13,
19396				CertCompressionAlgs: map[uint16]CertCompressionAlg{
19397					shrinkingCompressionAlgID: shrinkingCompression,
19398					expandingCompressionAlgID: expandingCompression,
19399				},
19400				Bugs: ProtocolBugs{
19401					// The shim's preferences should take effect.
19402					ExpectedCompressedCert: shrinkingCompressionAlgID,
19403				},
19404			},
19405			flags: []string{
19406				"-allow-hint-mismatch",
19407				"-on-shim-install-one-cert-compression-alg", strconv.Itoa(shrinkingCompressionAlgID),
19408				"-on-handshaker-install-one-cert-compression-alg", strconv.Itoa(expandingCompressionAlgID),
19409			},
19410		})
19411		testCases = append(testCases, testCase{
19412			testType:           serverTest,
19413			name:               protocol.String() + "-HintMismatch-CertificateCompression-InputMismatch",
19414			protocol:           protocol,
19415			skipSplitHandshake: true,
19416			config: Config{
19417				MinVersion: VersionTLS13,
19418				MaxVersion: VersionTLS13,
19419				CertCompressionAlgs: map[uint16]CertCompressionAlg{
19420					shrinkingCompressionAlgID: shrinkingCompression,
19421				},
19422				Bugs: ProtocolBugs{
19423					ExpectedCompressedCert: shrinkingCompressionAlgID,
19424				},
19425			},
19426			// Configure the shim and handshaker with different OCSP responses,
19427			// so the compression inputs do not match.
19428			shimCertificate:       rsaCertificate.WithOCSP(testOCSPResponse),
19429			handshakerCertificate: rsaCertificate.WithOCSP(testOCSPResponse2),
19430			flags: []string{
19431				"-allow-hint-mismatch",
19432				"-install-cert-compression-algs",
19433			},
19434			expectations: connectionExpectations{
19435				// The shim's configuration should take precendence.
19436				peerCertificate: rsaCertificate.WithOCSP(testOCSPResponse),
19437			},
19438		})
19439
19440		// The shim and handshaker may disagree on cipher suite, to the point
19441		// that one selects RSA key exchange (no applicable hint) and the other
19442		// selects ECDHE_RSA (hints are useful).
19443		if protocol != quic {
19444			testCases = append(testCases, testCase{
19445				testType:           serverTest,
19446				name:               protocol.String() + "-HintMismatch-CipherMismatch1",
19447				protocol:           protocol,
19448				skipSplitHandshake: true,
19449				config: Config{
19450					MinVersion: VersionTLS12,
19451					MaxVersion: VersionTLS12,
19452				},
19453				flags: []string{
19454					"-allow-hint-mismatch",
19455					"-on-shim-cipher", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
19456					"-on-handshaker-cipher", "TLS_RSA_WITH_AES_128_GCM_SHA256",
19457				},
19458				expectations: connectionExpectations{
19459					cipher: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
19460				},
19461			})
19462			testCases = append(testCases, testCase{
19463				testType:           serverTest,
19464				name:               protocol.String() + "-HintMismatch-CipherMismatch2",
19465				protocol:           protocol,
19466				skipSplitHandshake: true,
19467				config: Config{
19468					MinVersion: VersionTLS12,
19469					MaxVersion: VersionTLS12,
19470				},
19471				flags: []string{
19472					// There is no need to pass -allow-hint-mismatch. The
19473					// handshaker will unnecessarily generate a signature hints.
19474					// This is not reported as a mismatch because hints would
19475					// not have helped the shim anyway.
19476					"-on-shim-cipher", "TLS_RSA_WITH_AES_128_GCM_SHA256",
19477					"-on-handshaker-cipher", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
19478				},
19479				expectations: connectionExpectations{
19480					cipher: TLS_RSA_WITH_AES_128_GCM_SHA256,
19481				},
19482			})
19483		}
19484	}
19485}
19486
19487func addCompliancePolicyTests() {
19488	for _, protocol := range []protocol{tls, quic} {
19489		for _, suite := range testCipherSuites {
19490			var isFIPSCipherSuite bool
19491			switch suite.id {
19492			case TLS_AES_128_GCM_SHA256,
19493				TLS_AES_256_GCM_SHA384,
19494				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
19495				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
19496				TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
19497				TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
19498				isFIPSCipherSuite = true
19499			}
19500
19501			var isWPACipherSuite bool
19502			switch suite.id {
19503			case TLS_AES_256_GCM_SHA384,
19504				TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
19505				TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
19506				isWPACipherSuite = true
19507			}
19508
19509			var cert Credential
19510			if hasComponent(suite.name, "ECDSA") {
19511				cert = ecdsaP384Certificate
19512			} else {
19513				cert = rsaCertificate
19514			}
19515
19516			maxVersion := uint16(VersionTLS13)
19517			if !isTLS13Suite(suite.name) {
19518				if protocol == quic {
19519					continue
19520				}
19521				maxVersion = VersionTLS12
19522			}
19523
19524			policies := []struct {
19525				flag          string
19526				cipherSuiteOk bool
19527			}{
19528				{"-fips-202205", isFIPSCipherSuite},
19529				{"-wpa-202304", isWPACipherSuite},
19530			}
19531
19532			for _, policy := range policies {
19533				testCases = append(testCases, testCase{
19534					testType: serverTest,
19535					protocol: protocol,
19536					name:     "Compliance" + policy.flag + "-" + protocol.String() + "-Server-" + suite.name,
19537					config: Config{
19538						MinVersion:   VersionTLS12,
19539						MaxVersion:   maxVersion,
19540						CipherSuites: []uint16{suite.id},
19541					},
19542					shimCertificate: &cert,
19543					flags: []string{
19544						policy.flag,
19545					},
19546					shouldFail: !policy.cipherSuiteOk,
19547				})
19548
19549				testCases = append(testCases, testCase{
19550					testType: clientTest,
19551					protocol: protocol,
19552					name:     "Compliance" + policy.flag + "-" + protocol.String() + "-Client-" + suite.name,
19553					config: Config{
19554						MinVersion:   VersionTLS12,
19555						MaxVersion:   maxVersion,
19556						CipherSuites: []uint16{suite.id},
19557						Credential:   &cert,
19558					},
19559					flags: []string{
19560						policy.flag,
19561					},
19562					shouldFail: !policy.cipherSuiteOk,
19563				})
19564			}
19565		}
19566
19567		// Check that a TLS 1.3 client won't accept ChaCha20 even if the server
19568		// picks it without it being in the client's cipher list.
19569		testCases = append(testCases, testCase{
19570			testType: clientTest,
19571			protocol: protocol,
19572			name:     "Compliance-fips202205-" + protocol.String() + "-Client-ReallyWontAcceptChaCha",
19573			config: Config{
19574				MinVersion: VersionTLS12,
19575				MaxVersion: maxVersion,
19576				Bugs: ProtocolBugs{
19577					SendCipherSuite: TLS_CHACHA20_POLY1305_SHA256,
19578				},
19579			},
19580			flags: []string{
19581				"-fips-202205",
19582			},
19583			shouldFail:    true,
19584			expectedError: ":WRONG_CIPHER_RETURNED:",
19585		})
19586
19587		for _, curve := range testCurves {
19588			var isFIPSCurve bool
19589			switch curve.id {
19590			case CurveP256, CurveP384:
19591				isFIPSCurve = true
19592			}
19593
19594			var isWPACurve bool
19595			switch curve.id {
19596			case CurveP384:
19597				isWPACurve = true
19598			}
19599
19600			policies := []struct {
19601				flag    string
19602				curveOk bool
19603			}{
19604				{"-fips-202205", isFIPSCurve},
19605				{"-wpa-202304", isWPACurve},
19606			}
19607
19608			for _, policy := range policies {
19609				testCases = append(testCases, testCase{
19610					testType: serverTest,
19611					protocol: protocol,
19612					name:     "Compliance" + policy.flag + "-" + protocol.String() + "-Server-" + curve.name,
19613					config: Config{
19614						MinVersion:       VersionTLS12,
19615						MaxVersion:       VersionTLS13,
19616						CurvePreferences: []CurveID{curve.id},
19617					},
19618					flags: []string{
19619						policy.flag,
19620					},
19621					shouldFail: !policy.curveOk,
19622				})
19623
19624				testCases = append(testCases, testCase{
19625					testType: clientTest,
19626					protocol: protocol,
19627					name:     "Compliance" + policy.flag + "-" + protocol.String() + "-Client-" + curve.name,
19628					config: Config{
19629						MinVersion:       VersionTLS12,
19630						MaxVersion:       VersionTLS13,
19631						CurvePreferences: []CurveID{curve.id},
19632					},
19633					flags: []string{
19634						policy.flag,
19635					},
19636					shouldFail: !policy.curveOk,
19637				})
19638			}
19639		}
19640
19641		for _, sigalg := range testSignatureAlgorithms {
19642			// The TLS 1.0 and TLS 1.1 default signature algorithm does not
19643			// apply to these tests.
19644			if sigalg.id == 0 {
19645				continue
19646			}
19647
19648			var isFIPSSigAlg bool
19649			switch sigalg.id {
19650			case signatureRSAPKCS1WithSHA256,
19651				signatureRSAPKCS1WithSHA384,
19652				signatureRSAPKCS1WithSHA512,
19653				signatureECDSAWithP256AndSHA256,
19654				signatureECDSAWithP384AndSHA384,
19655				signatureRSAPSSWithSHA256,
19656				signatureRSAPSSWithSHA384,
19657				signatureRSAPSSWithSHA512:
19658				isFIPSSigAlg = true
19659			}
19660
19661			var isWPASigAlg bool
19662			switch sigalg.id {
19663			case signatureRSAPKCS1WithSHA384,
19664				signatureRSAPKCS1WithSHA512,
19665				signatureECDSAWithP384AndSHA384,
19666				signatureRSAPSSWithSHA384,
19667				signatureRSAPSSWithSHA512:
19668				isWPASigAlg = true
19669			}
19670
19671			if sigalg.curve == CurveP224 {
19672				// This can work in TLS 1.2, but not with TLS 1.3.
19673				// For consistency it's not permitted in FIPS mode.
19674				isFIPSSigAlg = false
19675			}
19676
19677			maxVersion := uint16(VersionTLS13)
19678			if hasComponent(sigalg.name, "PKCS1") {
19679				if protocol == quic {
19680					continue
19681				}
19682				maxVersion = VersionTLS12
19683			}
19684
19685			policies := []struct {
19686				flag     string
19687				sigAlgOk bool
19688			}{
19689				{"-fips-202205", isFIPSSigAlg},
19690				{"-wpa-202304", isWPASigAlg},
19691			}
19692
19693			cert := sigalg.baseCert.WithSignatureAlgorithms(sigalg.id)
19694			for _, policy := range policies {
19695				testCases = append(testCases, testCase{
19696					testType: serverTest,
19697					protocol: protocol,
19698					name:     "Compliance" + policy.flag + "-" + protocol.String() + "-Server-" + sigalg.name,
19699					config: Config{
19700						MinVersion:                VersionTLS12,
19701						MaxVersion:                maxVersion,
19702						VerifySignatureAlgorithms: []signatureAlgorithm{sigalg.id},
19703					},
19704					// Use the base certificate. We wish to pick up the signature algorithm
19705					// preferences from the FIPS policy.
19706					shimCertificate: sigalg.baseCert,
19707					flags:           []string{policy.flag},
19708					shouldFail:      !policy.sigAlgOk,
19709				})
19710
19711				testCases = append(testCases, testCase{
19712					testType: clientTest,
19713					protocol: protocol,
19714					name:     "Compliance" + policy.flag + "-" + protocol.String() + "-Client-" + sigalg.name,
19715					config: Config{
19716						MinVersion: VersionTLS12,
19717						MaxVersion: maxVersion,
19718						Credential: cert,
19719					},
19720					flags: []string{
19721						policy.flag,
19722					},
19723					shouldFail: !policy.sigAlgOk,
19724				})
19725			}
19726		}
19727	}
19728}
19729
19730func addCertificateSelectionTests() {
19731	// Combinatorially test each selection criteria at different versions,
19732	// protocols, and with the matching certificate before and after the
19733	// mismatching one.
19734	type certSelectTest struct {
19735		name          string
19736		testType      testType
19737		minVersion    uint16
19738		maxVersion    uint16
19739		config        Config
19740		match         *Credential
19741		mismatch      *Credential
19742		flags         []string
19743		expectedError string
19744	}
19745	certSelectTests := []certSelectTest{
19746		// TLS 1.0 through TLS 1.2 servers should incorporate TLS cipher suites
19747		// into certificate selection.
19748		{
19749			name:       "Server-CipherSuite-ECDHE_ECDSA",
19750			testType:   serverTest,
19751			maxVersion: VersionTLS12,
19752			config: Config{
19753				CipherSuites: []uint16{
19754					TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
19755				},
19756			},
19757			match:         &ecdsaP256Certificate,
19758			mismatch:      &rsaCertificate,
19759			expectedError: ":NO_SHARED_CIPHER:",
19760		},
19761		{
19762			name:       "Server-CipherSuite-ECDHE_RSA",
19763			testType:   serverTest,
19764			maxVersion: VersionTLS12,
19765			config: Config{
19766				CipherSuites: []uint16{
19767					TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
19768				},
19769			},
19770			match:         &rsaCertificate,
19771			mismatch:      &ecdsaP256Certificate,
19772			expectedError: ":NO_SHARED_CIPHER:",
19773		},
19774		{
19775			name:       "Server-CipherSuite-RSA",
19776			testType:   serverTest,
19777			maxVersion: VersionTLS12,
19778			config: Config{
19779				CipherSuites: []uint16{
19780					TLS_RSA_WITH_AES_128_CBC_SHA,
19781				},
19782			},
19783			match:         &rsaCertificate,
19784			mismatch:      &ecdsaP256Certificate,
19785			expectedError: ":NO_SHARED_CIPHER:",
19786		},
19787
19788		// Ed25519 counts as ECDSA for purposes of cipher suite matching.
19789		{
19790			name:       "Server-CipherSuite-ECDHE_ECDSA-Ed25519",
19791			testType:   serverTest,
19792			minVersion: VersionTLS12,
19793			maxVersion: VersionTLS12,
19794			config: Config{
19795				CipherSuites: []uint16{
19796					TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
19797				},
19798			},
19799			match:         &ed25519Certificate,
19800			mismatch:      &rsaCertificate,
19801			expectedError: ":NO_SHARED_CIPHER:",
19802		},
19803		{
19804			name:       "Server-CipherSuite-ECDHE_RSA-Ed25519",
19805			testType:   serverTest,
19806			minVersion: VersionTLS12,
19807			maxVersion: VersionTLS12,
19808			config: Config{
19809				CipherSuites: []uint16{
19810					TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
19811				},
19812			},
19813			match:         &rsaCertificate,
19814			mismatch:      &ed25519Certificate,
19815			expectedError: ":NO_SHARED_CIPHER:",
19816		},
19817
19818		// If there is no ECDHE curve match, ECDHE cipher suites are
19819		// disqualified in TLS 1.2 and below. This, in turn, impacts the
19820		// available cipher suites for each credential.
19821		{
19822			name:       "Server-CipherSuite-NoECDHE",
19823			testType:   serverTest,
19824			maxVersion: VersionTLS12,
19825			config: Config{
19826				CurvePreferences: []CurveID{CurveP256},
19827			},
19828			flags:         []string{"-curves", strconv.Itoa(int(CurveX25519))},
19829			match:         &rsaCertificate,
19830			mismatch:      &ecdsaP256Certificate,
19831			expectedError: ":NO_SHARED_CIPHER:",
19832		},
19833
19834		// If the client offered a cipher that would allow a certificate, but it
19835		// wasn't one of the ones we configured, the certificate should be
19836		// skipped in favor of another one.
19837		{
19838			name:       "Server-CipherSuite-Prefs",
19839			testType:   serverTest,
19840			maxVersion: VersionTLS12,
19841			config: Config{
19842				CipherSuites: []uint16{
19843					TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
19844					TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
19845				},
19846			},
19847			flags:         []string{"-cipher", "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA:TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"},
19848			match:         &rsaCertificate,
19849			mismatch:      &ecdsaP256Certificate,
19850			expectedError: ":NO_SHARED_CIPHER:",
19851		},
19852
19853		// TLS 1.0 through 1.2 servers should incorporate the curve list into
19854		// ECDSA certificate selection.
19855		{
19856			name:       "Server-Curve",
19857			testType:   serverTest,
19858			maxVersion: VersionTLS12,
19859			config: Config{
19860				CurvePreferences: []CurveID{CurveP256},
19861			},
19862			match:         &ecdsaP256Certificate,
19863			mismatch:      &ecdsaP384Certificate,
19864			expectedError: ":WRONG_CURVE:",
19865		},
19866
19867		// TLS 1.3 servers ignore the curve list. ECDSA certificate selection is
19868		// solely determined by the signature algorithm list.
19869		{
19870			name:       "Server-IgnoreCurve",
19871			testType:   serverTest,
19872			minVersion: VersionTLS13,
19873			config: Config{
19874				CurvePreferences: []CurveID{CurveP256},
19875			},
19876			match: &ecdsaP384Certificate,
19877		},
19878
19879		// TLS 1.2 servers also ignore the curve list for Ed25519. The signature
19880		// algorithm list is sufficient for Ed25519.
19881		{
19882			name:       "Server-IgnoreCurveEd25519",
19883			testType:   serverTest,
19884			minVersion: VersionTLS12,
19885			config: Config{
19886				CurvePreferences: []CurveID{CurveP256},
19887			},
19888			match: &ed25519Certificate,
19889		},
19890
19891		// Without signature algorithm negotiation, Ed25519 is not usable in TLS
19892		// 1.1 and below.
19893		{
19894			name:       "Server-NoEd25519",
19895			testType:   serverTest,
19896			maxVersion: VersionTLS11,
19897			match:      &rsaCertificate,
19898			mismatch:   &ed25519Certificate,
19899		},
19900
19901		// TLS 1.2 and up should incorporate the signature algorithm list into
19902		// certificate selection.
19903		{
19904			name:       "Server-SignatureAlgorithm",
19905			testType:   serverTest,
19906			minVersion: VersionTLS12,
19907			maxVersion: VersionTLS12,
19908			config: Config{
19909				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
19910				CipherSuites: []uint16{
19911					TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
19912					TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
19913				},
19914			},
19915			match:         &ecdsaP256Certificate,
19916			mismatch:      &rsaCertificate,
19917			expectedError: ":NO_SHARED_CIPHER:",
19918		},
19919		{
19920			name:       "Server-SignatureAlgorithm",
19921			testType:   serverTest,
19922			minVersion: VersionTLS13,
19923			config: Config{
19924				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
19925			},
19926			match:         &ecdsaP256Certificate,
19927			mismatch:      &rsaCertificate,
19928			expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
19929		},
19930
19931		// TLS 1.2's use of the signature algorithm list only disables the
19932		// signing-based algorithms. If an RSA key exchange cipher suite is
19933		// eligible, that is fine. (This is not a realistic configuration,
19934		// however. No one would configure RSA before ECDSA.)
19935		{
19936			name:       "Server-SignatureAlgorithmImpactsECDHEOnly",
19937			testType:   serverTest,
19938			minVersion: VersionTLS12,
19939			maxVersion: VersionTLS12,
19940			config: Config{
19941				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
19942				CipherSuites: []uint16{
19943					TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
19944					TLS_RSA_WITH_AES_128_CBC_SHA,
19945				},
19946			},
19947			match: &rsaCertificate,
19948		},
19949
19950		// TLS 1.3's use of the signature algorithm looks at the ECDSA curve
19951		// embedded in the signature algorithm.
19952		{
19953			name:       "Server-SignatureAlgorithmECDSACurve",
19954			testType:   serverTest,
19955			minVersion: VersionTLS13,
19956			config: Config{
19957				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
19958			},
19959			match:         &ecdsaP256Certificate,
19960			mismatch:      &ecdsaP384Certificate,
19961			expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
19962		},
19963
19964		// TLS 1.2's use does not.
19965		{
19966			name:       "Server-SignatureAlgorithmECDSACurve",
19967			testType:   serverTest,
19968			minVersion: VersionTLS12,
19969			maxVersion: VersionTLS12,
19970			config: Config{
19971				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
19972			},
19973			match: &ecdsaP384Certificate,
19974		},
19975
19976		// TLS 1.0 and 1.1 do not look at the signature algorithm.
19977		{
19978			name:       "Server-IgnoreSignatureAlgorithm",
19979			testType:   serverTest,
19980			maxVersion: VersionTLS11,
19981			config: Config{
19982				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
19983			},
19984			match: &rsaCertificate,
19985		},
19986
19987		// Signature algorithm matches take preferences on the keys into
19988		// consideration.
19989		{
19990			name:       "Server-SignatureAlgorithmKeyPrefs",
19991			testType:   serverTest,
19992			minVersion: VersionTLS12,
19993			maxVersion: VersionTLS12,
19994			config: Config{
19995				VerifySignatureAlgorithms: []signatureAlgorithm{signatureRSAPSSWithSHA256},
19996				CipherSuites:              []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
19997			},
19998			match:         rsaChainCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
19999			mismatch:      rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA384),
20000			expectedError: ":NO_SHARED_CIPHER:",
20001		},
20002		{
20003			name:       "Server-SignatureAlgorithmKeyPrefs",
20004			testType:   serverTest,
20005			minVersion: VersionTLS13,
20006			config: Config{
20007				VerifySignatureAlgorithms: []signatureAlgorithm{signatureRSAPSSWithSHA256},
20008			},
20009			match:         rsaChainCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
20010			mismatch:      rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA384),
20011			expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
20012		},
20013
20014		// TLS 1.2 clients and below check the certificate against the old
20015		// client certificate types field.
20016		{
20017			name:       "Client-ClientCertificateTypes-RSA",
20018			testType:   clientTest,
20019			maxVersion: VersionTLS12,
20020			config: Config{
20021				ClientAuth:             RequestClientCert,
20022				ClientCertificateTypes: []uint8{CertTypeRSASign},
20023			},
20024			match:         &rsaCertificate,
20025			mismatch:      &ecdsaP256Certificate,
20026			expectedError: ":UNKNOWN_CERTIFICATE_TYPE:",
20027		},
20028		{
20029			name:       "Client-ClientCertificateTypes-ECDSA",
20030			testType:   clientTest,
20031			maxVersion: VersionTLS12,
20032			config: Config{
20033				ClientAuth:             RequestClientCert,
20034				ClientCertificateTypes: []uint8{CertTypeECDSASign},
20035			},
20036			match:         &ecdsaP256Certificate,
20037			mismatch:      &rsaCertificate,
20038			expectedError: ":UNKNOWN_CERTIFICATE_TYPE:",
20039		},
20040
20041		// Ed25519 is considered ECDSA for purposes of client certificate types.
20042		{
20043			name:       "Client-ClientCertificateTypes-RSA-Ed25519",
20044			testType:   clientTest,
20045			minVersion: VersionTLS12,
20046			maxVersion: VersionTLS12,
20047			config: Config{
20048				ClientAuth:             RequestClientCert,
20049				ClientCertificateTypes: []uint8{CertTypeRSASign},
20050			},
20051			match:         &rsaCertificate,
20052			mismatch:      &ed25519Certificate,
20053			expectedError: ":UNKNOWN_CERTIFICATE_TYPE:",
20054		},
20055		{
20056			name:       "Client-ClientCertificateTypes-ECDSA-Ed25519",
20057			testType:   clientTest,
20058			minVersion: VersionTLS12,
20059			maxVersion: VersionTLS12,
20060			config: Config{
20061				ClientAuth:             RequestClientCert,
20062				ClientCertificateTypes: []uint8{CertTypeECDSASign},
20063			},
20064			match:         &ed25519Certificate,
20065			mismatch:      &rsaCertificate,
20066			expectedError: ":UNKNOWN_CERTIFICATE_TYPE:",
20067		},
20068
20069		// TLS 1.2 and up should incorporate the signature algorithm list into
20070		// certificate selection. (There is no signature algorithm list to look
20071		// at in TLS 1.0 and 1.1.)
20072		{
20073			name:       "Client-SignatureAlgorithm",
20074			testType:   clientTest,
20075			minVersion: VersionTLS12,
20076			config: Config{
20077				ClientAuth:                RequestClientCert,
20078				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
20079			},
20080			match:         &ecdsaP256Certificate,
20081			mismatch:      &rsaCertificate,
20082			expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
20083		},
20084
20085		// TLS 1.3's use of the signature algorithm looks at the ECDSA curve
20086		// embedded in the signature algorithm.
20087		{
20088			name:       "Client-SignatureAlgorithmECDSACurve",
20089			testType:   clientTest,
20090			minVersion: VersionTLS13,
20091			config: Config{
20092				ClientAuth:                RequestClientCert,
20093				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
20094			},
20095			match:         &ecdsaP256Certificate,
20096			mismatch:      &ecdsaP384Certificate,
20097			expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
20098		},
20099
20100		// TLS 1.2's use does not. It is not possible to determine what ECDSA
20101		// curves are allowed by the server.
20102		{
20103			name:       "Client-SignatureAlgorithmECDSACurve",
20104			testType:   clientTest,
20105			minVersion: VersionTLS12,
20106			maxVersion: VersionTLS12,
20107			config: Config{
20108				ClientAuth:                RequestClientCert,
20109				VerifySignatureAlgorithms: []signatureAlgorithm{signatureECDSAWithP256AndSHA256},
20110			},
20111			match: &ecdsaP384Certificate,
20112		},
20113
20114		// Signature algorithm matches take preferences on the keys into
20115		// consideration.
20116		{
20117			name:       "Client-SignatureAlgorithmKeyPrefs",
20118			testType:   clientTest,
20119			minVersion: VersionTLS12,
20120			config: Config{
20121				ClientAuth:                RequestClientCert,
20122				VerifySignatureAlgorithms: []signatureAlgorithm{signatureRSAPSSWithSHA256},
20123			},
20124			match:         rsaChainCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA256),
20125			mismatch:      rsaCertificate.WithSignatureAlgorithms(signatureRSAPSSWithSHA384),
20126			expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
20127		},
20128	}
20129
20130	for _, protocol := range []protocol{tls, dtls} {
20131		for _, vers := range allVersions(protocol) {
20132			suffix := fmt.Sprintf("%s-%s", protocol, vers)
20133
20134			// Test that the credential list is interpreted in preference order,
20135			// with the default credential, if any, at the end.
20136			testCases = append(testCases, testCase{
20137				name:     fmt.Sprintf("CertificateSelection-Client-PreferenceOrder-%s", suffix),
20138				testType: clientTest,
20139				protocol: protocol,
20140				config: Config{
20141					MinVersion: vers.version,
20142					MaxVersion: vers.version,
20143					ClientAuth: RequestClientCert,
20144				},
20145				shimCredentials: []*Credential{&ecdsaP256Certificate, &ecdsaP384Certificate},
20146				shimCertificate: &rsaCertificate,
20147				flags:           []string{"-expect-selected-credential", "0"},
20148				expectations:    connectionExpectations{peerCertificate: &ecdsaP256Certificate},
20149			})
20150			testCases = append(testCases, testCase{
20151				name:     fmt.Sprintf("CertificateSelection-Server-PreferenceOrder-%s", suffix),
20152				testType: serverTest,
20153				protocol: protocol,
20154				config: Config{
20155					MinVersion: vers.version,
20156					MaxVersion: vers.version,
20157				},
20158				shimCredentials: []*Credential{&ecdsaP256Certificate, &ecdsaP384Certificate},
20159				shimCertificate: &rsaCertificate,
20160				flags:           []string{"-expect-selected-credential", "0"},
20161				expectations:    connectionExpectations{peerCertificate: &ecdsaP256Certificate},
20162			})
20163
20164			// Test that the selected credential contributes the certificate chain, OCSP response,
20165			// and SCT list.
20166			testCases = append(testCases, testCase{
20167				name:     fmt.Sprintf("CertificateSelection-Server-OCSP-SCT-%s", suffix),
20168				testType: serverTest,
20169				protocol: protocol,
20170				config: Config{
20171					MinVersion: vers.version,
20172					MaxVersion: vers.version,
20173					// Configure enough options so that, at all TLS versions, only an RSA
20174					// certificate will be accepted.
20175					CipherSuites: []uint16{
20176						TLS_AES_128_GCM_SHA256,
20177						TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
20178						TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
20179					},
20180					VerifySignatureAlgorithms: []signatureAlgorithm{signatureRSAPSSWithSHA256},
20181				},
20182				shimCredentials: []*Credential{
20183					ecdsaP256Certificate.WithOCSP(testOCSPResponse2).WithSCTList(testSCTList2),
20184					rsaChainCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
20185				},
20186				shimCertificate: ecdsaP384Certificate.WithOCSP(testOCSPResponse2).WithSCTList(testSCTList2),
20187				flags:           []string{"-expect-selected-credential", "1"},
20188				expectations: connectionExpectations{
20189					peerCertificate: rsaChainCertificate.WithOCSP(testOCSPResponse).WithSCTList(testSCTList),
20190				},
20191			})
20192
20193			// Test that the credentials API works asynchronously. This tests both deferring the
20194			// configuration to the certificate callback, and using a custom, async private key.
20195			testCases = append(testCases, testCase{
20196				name:     fmt.Sprintf("CertificateSelection-Client-Async-%s", suffix),
20197				testType: clientTest,
20198				protocol: protocol,
20199				config: Config{
20200					MinVersion: vers.version,
20201					MaxVersion: vers.version,
20202					ClientAuth: RequestClientCert,
20203				},
20204				shimCredentials: []*Credential{&ecdsaP256Certificate},
20205				shimCertificate: &rsaCertificate,
20206				flags:           []string{"-async", "-expect-selected-credential", "0"},
20207				expectations:    connectionExpectations{peerCertificate: &ecdsaP256Certificate},
20208			})
20209			testCases = append(testCases, testCase{
20210				name:     fmt.Sprintf("CertificateSelection-Server-Async-%s", suffix),
20211				testType: serverTest,
20212				protocol: protocol,
20213				config: Config{
20214					MinVersion: vers.version,
20215					MaxVersion: vers.version,
20216				},
20217				shimCredentials: []*Credential{&ecdsaP256Certificate},
20218				shimCertificate: &rsaCertificate,
20219				flags:           []string{"-async", "-expect-selected-credential", "0"},
20220				expectations:    connectionExpectations{peerCertificate: &ecdsaP256Certificate},
20221			})
20222
20223			for _, test := range certSelectTests {
20224				if test.minVersion != 0 && vers.version < test.minVersion {
20225					continue
20226				}
20227				if test.maxVersion != 0 && vers.version > test.maxVersion {
20228					continue
20229				}
20230
20231				config := test.config
20232				config.MinVersion = vers.version
20233				config.MaxVersion = vers.version
20234
20235				// If the mismatch field is omitted, this is a positive test,
20236				// just to confirm that the selection logic does not block a
20237				// particular certificate.
20238				if test.mismatch == nil {
20239					testCases = append(testCases, testCase{
20240						name:            fmt.Sprintf("CertificateSelection-%s-%s", test.name, suffix),
20241						protocol:        protocol,
20242						testType:        test.testType,
20243						config:          config,
20244						shimCredentials: []*Credential{test.match},
20245						flags:           append([]string{"-expect-selected-credential", "0"}, test.flags...),
20246						expectations:    connectionExpectations{peerCertificate: test.match},
20247					})
20248					continue
20249				}
20250
20251				testCases = append(testCases, testCase{
20252					name:            fmt.Sprintf("CertificateSelection-%s-MatchFirst-%s", test.name, suffix),
20253					protocol:        protocol,
20254					testType:        test.testType,
20255					config:          config,
20256					shimCredentials: []*Credential{test.match, test.mismatch},
20257					flags:           append([]string{"-expect-selected-credential", "0"}, test.flags...),
20258					expectations:    connectionExpectations{peerCertificate: test.match},
20259				})
20260				testCases = append(testCases, testCase{
20261					name:            fmt.Sprintf("CertificateSelection-%s-MatchSecond-%s", test.name, suffix),
20262					protocol:        protocol,
20263					testType:        test.testType,
20264					config:          config,
20265					shimCredentials: []*Credential{test.mismatch, test.match},
20266					flags:           append([]string{"-expect-selected-credential", "1"}, test.flags...),
20267					expectations:    connectionExpectations{peerCertificate: test.match},
20268				})
20269				testCases = append(testCases, testCase{
20270					name:            fmt.Sprintf("CertificateSelection-%s-MatchDefault-%s", test.name, suffix),
20271					protocol:        protocol,
20272					testType:        test.testType,
20273					config:          config,
20274					shimCredentials: []*Credential{test.mismatch},
20275					shimCertificate: test.match,
20276					flags:           append([]string{"-expect-selected-credential", "-1"}, test.flags...),
20277					expectations:    connectionExpectations{peerCertificate: test.match},
20278				})
20279				testCases = append(testCases, testCase{
20280					name:               fmt.Sprintf("CertificateSelection-%s-MatchNone-%s", test.name, suffix),
20281					protocol:           protocol,
20282					testType:           test.testType,
20283					config:             config,
20284					shimCredentials:    []*Credential{test.mismatch, test.mismatch, test.mismatch},
20285					flags:              test.flags,
20286					shouldFail:         true,
20287					expectedLocalError: "remote error: handshake failure",
20288					expectedError:      test.expectedError,
20289				})
20290			}
20291		}
20292	}
20293}
20294
20295func worker(dispatcher *shimDispatcher, statusChan chan statusMsg, c chan *testCase, shimPath string, wg *sync.WaitGroup) {
20296	defer wg.Done()
20297
20298	for test := range c {
20299		var err error
20300
20301		if *mallocTest >= 0 {
20302			for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
20303				statusChan <- statusMsg{test: test, statusType: statusStarted}
20304				if err = runTest(dispatcher, statusChan, test, shimPath, mallocNumToFail); err != errMoreMallocs {
20305					if err != nil {
20306						fmt.Printf("\n\nmalloc test failed at %d: %s\n", mallocNumToFail, err)
20307					}
20308					break
20309				}
20310			}
20311		} else if *repeatUntilFailure {
20312			for err == nil {
20313				statusChan <- statusMsg{test: test, statusType: statusStarted}
20314				err = runTest(dispatcher, statusChan, test, shimPath, -1)
20315			}
20316		} else {
20317			statusChan <- statusMsg{test: test, statusType: statusStarted}
20318			err = runTest(dispatcher, statusChan, test, shimPath, -1)
20319		}
20320		statusChan <- statusMsg{test: test, statusType: statusDone, err: err}
20321	}
20322}
20323
20324type statusType int
20325
20326const (
20327	statusStarted statusType = iota
20328	statusShimStarted
20329	statusDone
20330)
20331
20332type statusMsg struct {
20333	test       *testCase
20334	statusType statusType
20335	pid        int
20336	err        error
20337}
20338
20339func statusPrinter(doneChan chan *testresult.Results, statusChan chan statusMsg, total int) {
20340	var started, done, failed, unimplemented, lineLen int
20341
20342	testOutput := testresult.NewResults()
20343	for msg := range statusChan {
20344		if !*pipe {
20345			// Erase the previous status line.
20346			var erase string
20347			for i := 0; i < lineLen; i++ {
20348				erase += "\b \b"
20349			}
20350			fmt.Print(erase)
20351		}
20352
20353		if msg.statusType == statusStarted {
20354			started++
20355		} else if msg.statusType == statusDone {
20356			done++
20357
20358			if msg.err != nil {
20359				if msg.err == errUnimplemented {
20360					if *pipe {
20361						// Print each test instead of a status line.
20362						fmt.Printf("UNIMPLEMENTED (%s)\n", msg.test.name)
20363					}
20364					unimplemented++
20365					if *allowUnimplemented {
20366						testOutput.AddSkip(msg.test.name)
20367					} else {
20368						testOutput.AddResult(msg.test.name, "SKIP")
20369					}
20370				} else {
20371					fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
20372					failed++
20373					testOutput.AddResult(msg.test.name, "FAIL")
20374				}
20375			} else {
20376				if *pipe {
20377					// Print each test instead of a status line.
20378					fmt.Printf("PASSED (%s)\n", msg.test.name)
20379				}
20380				testOutput.AddResult(msg.test.name, "PASS")
20381			}
20382		}
20383
20384		if !*pipe {
20385			// Print a new status line.
20386			line := fmt.Sprintf("%d/%d/%d/%d/%d", failed, unimplemented, done, started, total)
20387			if msg.statusType == statusShimStarted && *waitForDebugger {
20388				// Note -wait-for-debugger limits the test to one worker,
20389				// otherwise some output would be skipped.
20390				line += fmt.Sprintf(" (%s: attach to process %d to continue)", msg.test.name, msg.pid)
20391			}
20392			lineLen = len(line)
20393			os.Stdout.WriteString(line)
20394		}
20395	}
20396
20397	doneChan <- testOutput
20398}
20399
20400func match(oneOfPatternIfAny []string, noneOfPattern []string, candidate string) (matched bool, err error) {
20401	matched = len(oneOfPatternIfAny) == 0
20402
20403	var didMatch bool
20404	for _, pattern := range oneOfPatternIfAny {
20405		didMatch, err = filepath.Match(pattern, candidate)
20406		if err != nil {
20407			return false, err
20408		}
20409
20410		matched = didMatch || matched
20411	}
20412
20413	for _, pattern := range noneOfPattern {
20414		didMatch, err = filepath.Match(pattern, candidate)
20415		if err != nil {
20416			return false, err
20417		}
20418
20419		matched = !didMatch && matched
20420	}
20421
20422	return matched, nil
20423}
20424
20425func checkTests() {
20426	for _, test := range testCases {
20427		if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
20428			panic("Error expected without shouldFail in " + test.name)
20429		}
20430
20431		if test.expectResumeRejected && !test.resumeSession {
20432			panic("expectResumeRejected without resumeSession in " + test.name)
20433		}
20434
20435		if !test.skipVersionNameCheck {
20436			for _, ver := range tlsVersions {
20437				if !strings.Contains("-"+test.name+"-", "-"+ver.name+"-") {
20438					continue
20439				}
20440
20441				found := test.config.MaxVersion == ver.version || test.config.MinVersion == ver.version || test.expectations.version == ver.version
20442				if test.resumeConfig != nil {
20443					found = found || test.resumeConfig.MaxVersion == ver.version || test.resumeConfig.MinVersion == ver.version
20444				}
20445				if test.resumeExpectations != nil {
20446					found = found || test.resumeExpectations.version == ver.version
20447				}
20448				shimFlag := ver.shimFlag(test.protocol)
20449				for _, flag := range test.flags {
20450					if flag == shimFlag {
20451						found = true
20452						break
20453					}
20454				}
20455				if !found {
20456					panic(fmt.Sprintf("The name of test %q suggests that it's version specific, but the test does not reference %s", test.name, ver.name))
20457				}
20458			}
20459		}
20460
20461		for _, protocol := range []protocol{tls, dtls, quic} {
20462			if strings.Contains("-"+test.name+"-", "-"+protocol.String()+"-") && test.protocol != protocol {
20463				panic(fmt.Sprintf("The name of test %q suggests that it tests %q, but the test does not reference it", test.name, protocol))
20464			}
20465		}
20466	}
20467}
20468
20469func main() {
20470	flag.Parse()
20471	var err error
20472	if tmpDir, err = os.MkdirTemp("", "testing-certs"); err != nil {
20473		fmt.Fprintf(os.Stderr, "failed to make temporary directory: %s", err)
20474		os.Exit(1)
20475	}
20476	defer os.RemoveAll(tmpDir)
20477	initKeys()
20478	initCertificates()
20479
20480	if len(*shimConfigFile) != 0 {
20481		encoded, err := os.ReadFile(*shimConfigFile)
20482		if err != nil {
20483			fmt.Fprintf(os.Stderr, "Couldn't read config file %q: %s\n", *shimConfigFile, err)
20484			os.Exit(1)
20485		}
20486
20487		if err := json.Unmarshal(encoded, &shimConfig); err != nil {
20488			fmt.Fprintf(os.Stderr, "Couldn't decode config file %q: %s\n", *shimConfigFile, err)
20489			os.Exit(1)
20490		}
20491	}
20492
20493	if shimConfig.AllCurves == nil {
20494		for _, curve := range testCurves {
20495			shimConfig.AllCurves = append(shimConfig.AllCurves, int(curve.id))
20496		}
20497	}
20498
20499	addBasicTests()
20500	addCipherSuiteTests()
20501	addBadECDSASignatureTests()
20502	addCBCPaddingTests()
20503	addCBCSplittingTests()
20504	addClientAuthTests()
20505	addDDoSCallbackTests()
20506	addVersionNegotiationTests()
20507	addMinimumVersionTests()
20508	addExtensionTests()
20509	addResumptionVersionTests()
20510	addExtendedMasterSecretTests()
20511	addRenegotiationTests()
20512	addDTLSReplayTests()
20513	addSignatureAlgorithmTests()
20514	addDTLSRetransmitTests()
20515	addExportKeyingMaterialTests()
20516	addExportTrafficSecretsTests()
20517	addTLSUniqueTests()
20518	addCustomExtensionTests()
20519	addRSAClientKeyExchangeTests()
20520	addCurveTests()
20521	addSessionTicketTests()
20522	addTLS13RecordTests()
20523	addAllStateMachineCoverageTests()
20524	addChangeCipherSpecTests()
20525	addEndOfFlightTests()
20526	addWrongMessageTypeTests()
20527	addTrailingMessageDataTests()
20528	addTLS13HandshakeTests()
20529	addTLS13CipherPreferenceTests()
20530	addPeekTests()
20531	addRecordVersionTests()
20532	addCertificateTests()
20533	addRetainOnlySHA256ClientCertTests()
20534	addECDSAKeyUsageTests()
20535	addRSAKeyUsageTests()
20536	addExtraHandshakeTests()
20537	addOmitExtensionsTests()
20538	addCertCompressionTests()
20539	addJDK11WorkaroundTests()
20540	addDelegatedCredentialTests()
20541	addEncryptedClientHelloTests()
20542	addHintMismatchTests()
20543	addCompliancePolicyTests()
20544	addCertificateSelectionTests()
20545
20546	toAppend, err := convertToSplitHandshakeTests(testCases)
20547	if err != nil {
20548		fmt.Fprintf(os.Stderr, "Error making split handshake tests: %s", err)
20549		os.Exit(1)
20550	}
20551	testCases = append(testCases, toAppend...)
20552
20553	checkTests()
20554
20555	dispatcher, err := newShimDispatcher()
20556	if err != nil {
20557		fmt.Fprintf(os.Stderr, "Error opening socket: %s", err)
20558		os.Exit(1)
20559	}
20560	defer dispatcher.Close()
20561
20562	numWorkers := *numWorkersFlag
20563	if useDebugger() {
20564		numWorkers = 1
20565	}
20566
20567	statusChan := make(chan statusMsg, numWorkers)
20568	testChan := make(chan *testCase, numWorkers)
20569	doneChan := make(chan *testresult.Results)
20570
20571	go statusPrinter(doneChan, statusChan, len(testCases))
20572
20573	var wg sync.WaitGroup
20574	for i := 0; i < numWorkers; i++ {
20575		wg.Add(1)
20576		go worker(dispatcher, statusChan, testChan, *shimPath, &wg)
20577	}
20578
20579	var oneOfPatternIfAny, noneOfPattern []string
20580	if len(*testToRun) > 0 {
20581		oneOfPatternIfAny = strings.Split(*testToRun, ";")
20582	}
20583	if len(*skipTest) > 0 {
20584		noneOfPattern = strings.Split(*skipTest, ";")
20585	}
20586
20587	shardIndex, shardTotal, err := getSharding()
20588	if err != nil {
20589		fmt.Fprintln(os.Stderr, err)
20590		os.Exit(1)
20591	}
20592
20593	if shardTotal > 0 {
20594		fmt.Printf("This is shard %d of 0..%d (inclusive)\n", shardIndex, shardTotal-1)
20595	}
20596
20597	var foundTest bool
20598	for i := range testCases {
20599		if shardTotal > 0 && i%shardTotal != shardIndex {
20600			continue
20601		}
20602
20603		matched, err := match(oneOfPatternIfAny, noneOfPattern, testCases[i].name)
20604		if err != nil {
20605			fmt.Fprintf(os.Stderr, "Error matching pattern: %s\n", err)
20606			os.Exit(1)
20607		}
20608
20609		if !*includeDisabled {
20610			for pattern := range shimConfig.DisabledTests {
20611				isDisabled, err := filepath.Match(pattern, testCases[i].name)
20612				if err != nil {
20613					fmt.Fprintf(os.Stderr, "Error matching pattern %q from config file: %s\n", pattern, err)
20614					os.Exit(1)
20615				}
20616
20617				if isDisabled {
20618					matched = false
20619					break
20620				}
20621			}
20622		}
20623
20624		if matched {
20625			if foundTest && *useRR {
20626				fmt.Fprintf(os.Stderr, "Too many matching tests. Only one test can run when RR is enabled.\n")
20627				os.Exit(1)
20628			}
20629
20630			foundTest = true
20631			testChan <- &testCases[i]
20632
20633			// Only run one test if repeating until failure.
20634			if *repeatUntilFailure {
20635				break
20636			}
20637		}
20638	}
20639
20640	if !foundTest && shardTotal == 0 {
20641		fmt.Fprintf(os.Stderr, "No tests run\n")
20642		os.Exit(1)
20643	}
20644
20645	close(testChan)
20646	wg.Wait()
20647	close(statusChan)
20648	testOutput := <-doneChan
20649
20650	fmt.Printf("\n")
20651
20652	if *jsonOutput != "" {
20653		if err := testOutput.WriteToFile(*jsonOutput); err != nil {
20654			fmt.Fprintf(os.Stderr, "Error: %s\n", err)
20655		}
20656	}
20657
20658	if *useRR {
20659		fmt.Println("RR trace recorded. Replay with `rr replay`.")
20660	}
20661
20662	if !testOutput.HasUnexpectedResults() {
20663		os.Exit(1)
20664	}
20665}
20666